static void convert_cat(String *cap, char *s, Config *c, int maxlen) { int res; if (config_get_boolean(c, "/enfle/plugins/ui/normal/filename_code_conversion", &res)) { char **froms = config_get_list(c, "/enfle/plugins/ui/normal/filename_code_from", &res); char *to = config_get_str(c, "/enfle/plugins/ui/normal/filename_code_to"); char *from; int i = 0; if (res && to) { while ((from = froms[i++])) { char *tmp; //debug_message_fnc("%s->%s: %s\n", from, to, s); if ((res = converter_convert(s, &tmp, strlen(s), from, to)) < 0) continue; if (maxlen) string_ncat(cap, tmp, maxlen); else string_cat(cap, tmp); free(tmp); return; } } } if (maxlen > 0) string_ncat(cap, s, maxlen); else string_cat(cap, s); }
void web_server_threading_selection(void) { int threaded = config_get_boolean("global", "multi threaded web server", 1); int i; for(i = 0; static_threads[i].name ; i++) { if(static_threads[i].start_routine == socket_listen_main_multi_threaded) static_threads[i].enabled = threaded?1:0; if(static_threads[i].start_routine == socket_listen_main_single_threaded) static_threads[i].enabled = threaded?0:1; } web_client_timeout = (int) config_get_number("global", "disconnect idle web clients after seconds", DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS); web_donotrack_comply = config_get_boolean("global", "respect web browser do not track policy", web_donotrack_comply); #ifdef NETDATA_WITH_ZLIB web_enable_gzip = config_get_boolean("global", "enable web responses gzip compression", web_enable_gzip); char *s = config_get("global", "web compression strategy", "default"); if(!strcmp(s, "default")) web_gzip_strategy = Z_DEFAULT_STRATEGY; else if(!strcmp(s, "filtered")) web_gzip_strategy = Z_FILTERED; else if(!strcmp(s, "huffman only")) web_gzip_strategy = Z_HUFFMAN_ONLY; else if(!strcmp(s, "rle")) web_gzip_strategy = Z_RLE; else if(!strcmp(s, "fixed")) web_gzip_strategy = Z_FIXED; else { error("Invalid compression strategy '%s'. Valid strategies are 'default', 'filtered', 'huffman only', 'rle' and 'fixed'. Proceeding with 'default'.", s); web_gzip_strategy = Z_DEFAULT_STRATEGY; } web_gzip_level = (int)config_get_number("global", "web compression level", 3); if(web_gzip_level < 1) { error("Invalid compression level %d. Valid levels are 1 (fastest) to 9 (best ratio). Proceeding with level 1 (fastest compression).", web_gzip_level); web_gzip_level = 1; } else if(web_gzip_level > 9) { error("Invalid compression level %d. Valid levels are 1 (fastest) to 9 (best ratio). Proceeding with level 9 (best compression).", web_gzip_level); web_gzip_level = 9; } #endif /* NETDATA_WITH_ZLIB */ }
void read_cgroup_plugin_configuration() { cgroup_check_for_new_every = config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every); cgroup_enable_cpuacct_stat = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct stat", cgroup_enable_cpuacct_stat); cgroup_enable_cpuacct_usage = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct usage", cgroup_enable_cpuacct_usage); cgroup_enable_memory = config_get_boolean_ondemand("plugin:cgroups", "enable memory", cgroup_enable_memory); cgroup_enable_blkio = config_get_boolean_ondemand("plugin:cgroups", "enable blkio", cgroup_enable_blkio); char filename[FILENAME_MAX + 1], *s; struct mountinfo *mi, *root = mountinfo_read(); mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "cpuacct"); if(!mi) mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "cpuacct"); if(!mi) { error("Cannot find cgroup cpuacct mountinfo. Assuming default: /sys/fs/cgroup/cpuacct"); s = "/sys/fs/cgroup/cpuacct"; } else s = mi->mount_point; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s); cgroup_cpuacct_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/cpuacct", filename); mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "blkio"); if(!mi) mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "blkio"); if(!mi) { error("Cannot find cgroup blkio mountinfo. Assuming default: /sys/fs/cgroup/blkio"); s = "/sys/fs/cgroup/blkio"; } else s = mi->mount_point; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s); cgroup_blkio_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/blkio", filename); mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "memory"); if(!mi) mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "memory"); if(!mi) { error("Cannot find cgroup memory mountinfo. Assuming default: /sys/fs/cgroup/memory"); s = "/sys/fs/cgroup/memory"; } else s = mi->mount_point; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s); cgroup_memory_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/memory", filename); mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "devices"); if(!mi) mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "devices"); if(!mi) { error("Cannot find cgroup devices mountinfo. Assuming default: /sys/fs/cgroup/devices"); s = "/sys/fs/cgroup/devices"; } else s = mi->mount_point; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s); cgroup_devices_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/devices", filename); cgroup_root_max = config_get_number("plugin:cgroups", "max cgroups to allow", cgroup_root_max); cgroup_max_depth = config_get_number("plugin:cgroups", "max cgroups depth to monitor", cgroup_max_depth); cgroup_enable_new_cgroups_detected_at_runtime = config_get_boolean("plugin:cgroups", "enable new cgroups detected at run time", cgroup_enable_new_cgroups_detected_at_runtime); mountinfo_free(root); }
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); 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", ""); if(!*web_x_frame_options) web_x_frame_options = NULL; web_allow_connections_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow connections from", "localhost *"), NULL, SIMPLE_PATTERN_EXACT); web_allow_dashboard_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow dashboard from", "localhost *"), NULL, SIMPLE_PATTERN_EXACT); web_allow_badges_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow badges from", "*"), NULL, SIMPLE_PATTERN_EXACT); web_allow_registry_from = simple_pattern_create(config_get(CONFIG_SECTION_REGISTRY, "allow from", "*"), NULL, SIMPLE_PATTERN_EXACT); web_allow_streaming_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow streaming from", "*"), NULL, SIMPLE_PATTERN_EXACT); web_allow_netdataconf_from = simple_pattern_create(config_get(CONFIG_SECTION_WEB, "allow netdata.conf from", "localhost fd* 10.* 192.168.* 172.16.* 172.17.* 172.18.* 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.* 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.* 172.31.*"), NULL, SIMPLE_PATTERN_EXACT); #ifdef NETDATA_WITH_ZLIB web_enable_gzip = config_get_boolean(CONFIG_SECTION_WEB, "enable gzip compression", web_enable_gzip); char *s = config_get(CONFIG_SECTION_WEB, "gzip compression strategy", "default"); if(!strcmp(s, "default")) web_gzip_strategy = Z_DEFAULT_STRATEGY; else if(!strcmp(s, "filtered")) web_gzip_strategy = Z_FILTERED; else if(!strcmp(s, "huffman only")) web_gzip_strategy = Z_HUFFMAN_ONLY; else if(!strcmp(s, "rle")) web_gzip_strategy = Z_RLE; else if(!strcmp(s, "fixed")) web_gzip_strategy = Z_FIXED; else { error("Invalid compression strategy '%s'. Valid strategies are 'default', 'filtered', 'huffman only', 'rle' and 'fixed'. Proceeding with 'default'.", s); web_gzip_strategy = Z_DEFAULT_STRATEGY; } web_gzip_level = (int)config_get_number(CONFIG_SECTION_WEB, "gzip compression level", 3); if(web_gzip_level < 1) { error("Invalid compression level %d. Valid levels are 1 (fastest) to 9 (best ratio). Proceeding with level 1 (fastest compression).", web_gzip_level); web_gzip_level = 1; } else if(web_gzip_level > 9) { error("Invalid compression level %d. Valid levels are 1 (fastest) to 9 (best ratio). Proceeding with level 9 (best compression).", web_gzip_level); web_gzip_level = 9; } #endif /* NETDATA_WITH_ZLIB */ }
int notifications_init(config_t *config) { // Configure boxcar notifications if enabled if (config_get_boolean(config, "boxcar.enabled", 0)) { boxcar = boxcar_alloc(config); if (boxcar == NULL) { return -1; } } // Configure email notifications if enabled if (config_get_boolean(config, "email.enabled", 0)) { email = email_alloc(config); if (email == NULL) { return -1; } } return 0; }
int main(int argc, char **argv) { BkgdEvoMdlData *data; Config *config; if(argc != 2) { fprintf(stderr, "usage: %s <config_file>", argv[0]); exit(2); } fprintf(stderr, "Reading config\n"); config = config_read_file(argv[1], CONFIG_MISSING_KEY_ERROR); data = bkgd_data_read_data(config); if(config_get_boolean(config, "COMBINE_CAT_BINS")) { double min_cat, max_cat; min_cat = config_get_double(config, "MIN_CAT"); max_cat = config_get_double(config, "MAX_CAT"); bkgd_data_combine_cat_bin(data, min_cat, max_cat); } if(config_get_boolean(config, "COMBINE_DATA_BINS")) { long n_bin = config_get_long(config, "N_DATA_BIN"); bkgd_data_combine_bin(data, n_bin); } if(config_get_boolean(config, "WRITE_COUNTS")) { bkgd_data_write_site_counts(stdout, data); } if(config_get_boolean(config, "WRITE_BINS")) { write_data(stdout, data); } g_free(data->bin); g_free(data); return 0; }
static void backwards_compatible_config() { // allow existing configurations to work with the current version of netdata if(config_exists(CONFIG_SECTION_GLOBAL, "multi threaded web server")) { int mode = config_get_boolean(CONFIG_SECTION_GLOBAL, "multi threaded web server", 1); web_server_mode = (mode)?WEB_SERVER_MODE_MULTI_THREADED:WEB_SERVER_MODE_SINGLE_THREADED; } // move [global] options to the [web] section config_move(CONFIG_SECTION_GLOBAL, "http port listen backlog", CONFIG_SECTION_WEB, "listen backlog"); config_move(CONFIG_SECTION_GLOBAL, "bind socket to IP", CONFIG_SECTION_WEB, "bind to"); config_move(CONFIG_SECTION_GLOBAL, "bind to", CONFIG_SECTION_WEB, "bind to"); config_move(CONFIG_SECTION_GLOBAL, "port", CONFIG_SECTION_WEB, "default port"); config_move(CONFIG_SECTION_GLOBAL, "default port", CONFIG_SECTION_WEB, "default port"); config_move(CONFIG_SECTION_GLOBAL, "disconnect idle web clients after seconds", CONFIG_SECTION_WEB, "disconnect idle clients after seconds"); config_move(CONFIG_SECTION_GLOBAL, "respect web browser do not track policy", CONFIG_SECTION_WEB, "respect do not track policy"); config_move(CONFIG_SECTION_GLOBAL, "web x-frame-options header", CONFIG_SECTION_WEB, "x-frame-options response header"); config_move(CONFIG_SECTION_GLOBAL, "enable web responses gzip compression", CONFIG_SECTION_WEB, "enable gzip compression"); config_move(CONFIG_SECTION_GLOBAL, "web compression strategy", CONFIG_SECTION_WEB, "gzip compression strategy"); config_move(CONFIG_SECTION_GLOBAL, "web compression level", CONFIG_SECTION_WEB, "gzip compression level"); config_move(CONFIG_SECTION_GLOBAL, "web files owner", CONFIG_SECTION_WEB, "web files owner"); config_move(CONFIG_SECTION_GLOBAL, "web files group", CONFIG_SECTION_WEB, "web files group"); config_move(CONFIG_SECTION_BACKEND, "opentsdb host tags", CONFIG_SECTION_BACKEND, "host tags"); }
static inline void tc_device_commit(struct tc_device *d) { static int enable_new_interfaces = -1; if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean("plugin:tc", "enable new interfaces detected at runtime", 1); // we only need to add leaf classes struct tc_class *c, *x; // set all classes for(c = d->classes ; c ; c = c->next) { c->isleaf = 1; c->hasparent = 0; } // mark the classes as leafs and parents for(c = d->classes ; c ; c = c->next) { if(!c->updated) continue; for(x = d->classes ; x ; x = x->next) { if(!x->updated) continue; if(c == x) continue; if(x->parentid && ( ( c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) || (c->leafid && c->leaf_hash == x->parent_hash && strcmp(c->leafid, x->parentid) == 0))) { // debug(D_TC_LOOP, "TC: In device '%s', class '%s' (leafid: '%s') has as leaf class '%s' (parentid: '%s').", d->name?d->name:d->id, c->name?c->name:c->id, c->leafid?c->leafid:c->id, x->name?x->name:x->id, x->parentid?x->parentid:x->id); c->isleaf = 0; x->hasparent = 1; } } } // debugging: /* for ( c = d->classes ; c ; c = c->next) { if(c->isleaf && c->hasparent) debug(D_TC_LOOP, "TC: Device %s, class %s, OK", d->name, c->id); else debug(D_TC_LOOP, "TC: Device %s, class %s, IGNORE (isleaf: %d, hasparent: %d, parent: %s)", d->name, c->id, c->isleaf, c->hasparent, c->parentid); } */ // we need at least a class for(c = d->classes ; c ; c = c->next) { // debug(D_TC_LOOP, "TC: Device '%s', class '%s', isLeaf=%d, HasParent=%d, Seen=%d", d->name?d->name:d->id, c->name?c->name:c->id, c->isleaf, c->hasparent, c->seen); if(!c->updated) continue; if(c->isleaf && c->hasparent) break; } if(!c) { debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. No leaf classes.", d->name?d->name:d->id); tc_device_classes_cleanup(d); return; } char var_name[CONFIG_MAX_NAME + 1]; snprintfz(var_name, CONFIG_MAX_NAME, "qos for %s", d->id); if(config_get_boolean("plugin:tc", var_name, enable_new_interfaces)) { RRDSET *st = rrdset_find_bytype(RRD_TYPE_TC, d->id); if(!st) { debug(D_TC_LOOP, "TC: Creating new chart for device '%s'", d->name?d->name:d->id); st = rrdset_create(RRD_TYPE_TC, d->id, d->name?d->name:d->id, d->family?d->family:d->id, RRD_TYPE_TC ".qos", "Class Usage", "kilobits/s", 7000, rrd_update_every, RRDSET_TYPE_STACKED); for(c = d->classes ; c ; c = c->next) { if(!c->updated) continue; if(c->isleaf && c->hasparent) rrddim_add(st, c->id, c->name?c->name:c->id, 8, 1024, RRDDIM_INCREMENTAL); } } else { debug(D_TC_LOOP, "TC: Updating chart for device '%s'", d->name?d->name:d->id); rrdset_next_plugins(st); if(d->name && strcmp(d->id, d->name) != 0) rrdset_set_name(st, d->name); } for(c = d->classes ; c ; c = c->next) { if(!c->updated) continue; if(c->isleaf && c->hasparent) { RRDDIM *rd = rrddim_find(st, c->id); if(!rd) { debug(D_TC_LOOP, "TC: Adding to chart '%s', dimension '%s'", st->id, c->id, c->name); // new class, we have to add it rd = rrddim_add(st, c->id, c->name?c->name:c->id, 8, 1024, RRDDIM_INCREMENTAL); } else debug(D_TC_LOOP, "TC: Updating chart '%s', dimension '%s'", st->id, c->id); rrddim_set_by_pointer(st, rd, c->bytes); // if it has a name, different to the id if(c->name) { // update the rrd dimension with the new name debug(D_TC_LOOP, "TC: Setting chart '%s', dimension '%s' name to '%s'", st->id, rd->id, c->name); rrddim_set_name(st, rd, c->name); free(c->name); c->name = NULL; } } } rrdset_done(st); } tc_device_classes_cleanup(d); }
int do_proc_stat(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1; static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked; if(unlikely(do_cpu == -1)) { do_cpu = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", 1); do_cpu_cores = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", 1); do_interrupts = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", 1); do_context = config_get_boolean("plugin:proc:/proc/stat", "context switches", 1); do_forks = config_get_boolean("plugin:proc:/proc/stat", "processes started", 1); do_processes = config_get_boolean("plugin:proc:/proc/stat", "processes running", 1); hash_intr = simple_hash("intr"); hash_ctxt = simple_hash("ctxt"); hash_processes = simple_hash("processes"); hash_procs_running = simple_hash("procs_running"); hash_procs_blocked = simple_hash("procs_blocked"); } if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/stat"); ff = procfile_open(config_get("plugin:proc:/proc/stat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return 1; } ff = procfile_readall(ff); if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; uint32_t words; unsigned long long processes = 0, running = 0 , blocked = 0; RRDSET *st; for(l = 0; l < lines ;l++) { char *row_key = procfile_lineword(ff, l, 0); uint32_t hash = simple_hash(row_key); // faster strncmp(row_key, "cpu", 3) == 0 if(likely(row_key[0] == 'c' && row_key[1] == 'p' && row_key[2] == 'u')) { words = procfile_linewords(ff, l); if(unlikely(words < 9)) { error("Cannot read /proc/stat cpu line. Expected 9 params, read %u.", words); continue; } char *id; unsigned long long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0; id = row_key; user = strtoull(procfile_lineword(ff, l, 1), NULL, 10); nice = strtoull(procfile_lineword(ff, l, 2), NULL, 10); system = strtoull(procfile_lineword(ff, l, 3), NULL, 10); idle = strtoull(procfile_lineword(ff, l, 4), NULL, 10); iowait = strtoull(procfile_lineword(ff, l, 5), NULL, 10); irq = strtoull(procfile_lineword(ff, l, 6), NULL, 10); softirq = strtoull(procfile_lineword(ff, l, 7), NULL, 10); steal = strtoull(procfile_lineword(ff, l, 8), NULL, 10); guest = strtoull(procfile_lineword(ff, l, 9), NULL, 10); user -= guest; guest_nice = strtoull(procfile_lineword(ff, l, 10), NULL, 10); nice -= guest_nice; char *title, *type, *context, *family; long priority; int isthistotal; if(unlikely(strcmp(id, "cpu")) == 0) { title = "Total CPU utilization"; type = "system"; context = "system.cpu"; family = id; priority = 100; isthistotal = 1; } else { title = "Core utilization"; type = "cpu"; context = "cpu.cpu"; family = "utilization"; priority = 1000; isthistotal = 0; } if(likely((isthistotal && do_cpu) || (!isthistotal && do_cpu_cores))) { st = rrdset_find_bytype(type, id); if(unlikely(!st)) { st = rrdset_create(type, id, NULL, family, context, title, "percentage", priority, update_every, RRDSET_TYPE_STACKED); long multiplier = 1; long divisor = 1; // sysconf(_SC_CLK_TCK); rrddim_add(st, "guest_nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "guest", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "steal", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "softirq", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "irq", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "user", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "system", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "nice", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "iowait", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "idle", NULL, multiplier, divisor, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_hide(st, "idle"); } else rrdset_next(st); rrddim_set(st, "user", user); rrddim_set(st, "nice", nice); rrddim_set(st, "system", system); rrddim_set(st, "idle", idle); rrddim_set(st, "iowait", iowait); rrddim_set(st, "irq", irq); rrddim_set(st, "softirq", softirq); rrddim_set(st, "steal", steal); rrddim_set(st, "guest", guest); rrddim_set(st, "guest_nice", guest_nice); rrdset_done(st); } } else if(unlikely(hash == hash_intr && strcmp(row_key, "intr") == 0)) { unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10); // -------------------------------------------------------------------- if(likely(do_interrupts)) { st = rrdset_find_bytype("system", "intr"); if(unlikely(!st)) { st = rrdset_create("system", "intr", NULL, "interrupts", NULL, "CPU Interrupts", "interrupts/s", 900, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "interrupts", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "interrupts", value); rrdset_done(st); } } else if(unlikely(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0)) { unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10); // -------------------------------------------------------------------- if(likely(do_context)) { st = rrdset_find_bytype("system", "ctxt"); if(unlikely(!st)) { st = rrdset_create("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches", "context switches/s", 800, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "switches", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "switches", value); rrdset_done(st); } } else if(unlikely(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0)) { processes = strtoull(procfile_lineword(ff, l, 1), NULL, 10); } else if(unlikely(hash == hash_procs_running && !running && strcmp(row_key, "procs_running") == 0)) { running = strtoull(procfile_lineword(ff, l, 1), NULL, 10); } else if(unlikely(hash == hash_procs_blocked && !blocked && strcmp(row_key, "procs_blocked") == 0)) { blocked = strtoull(procfile_lineword(ff, l, 1), NULL, 10); } } // -------------------------------------------------------------------- if(likely(do_forks)) { st = rrdset_find_bytype("system", "forks"); if(unlikely(!st)) { st = rrdset_create("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s", 700, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "started", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "started", processes); rrdset_done(st); } // -------------------------------------------------------------------- if(likely(do_processes)) { st = rrdset_find_bytype("system", "processes"); if(unlikely(!st)) { st = rrdset_create("system", "processes", NULL, "processes", NULL, "System Processes", "processes", 600, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "running", NULL, 1, 1, RRDDIM_ABSOLUTE); rrddim_add(st, "blocked", NULL, -1, 1, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "running", running); rrddim_set(st, "blocked", blocked); rrdset_done(st); } return 0; }
int do_proc_net_ip_vs_stats(int update_every, unsigned long long 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(dt) {}; if(!ff) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_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); } 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 // make sure we have 3 lines if(procfile_lines(ff) < 3) return 1; // make sure we have 5 words on the 3rd line if(procfile_linewords(ff, 2) < 5) return 1; unsigned long long entries, InPackets, OutPackets, InBytes, OutBytes; entries = strtoull(procfile_lineword(ff, 2, 0), NULL, 16); InPackets = strtoull(procfile_lineword(ff, 2, 1), NULL, 16); OutPackets = strtoull(procfile_lineword(ff, 2, 2), NULL, 16); InBytes = strtoull(procfile_lineword(ff, 2, 3), NULL, 16); OutBytes = strtoull(procfile_lineword(ff, 2, 4), NULL, 16); RRDSET *st; // -------------------------------------------------------------------- if(do_sockets) { st = rrdset_find(RRD_TYPE_NET_IPVS ".sockets"); if(!st) { st = rrdset_create(RRD_TYPE_NET_IPVS, "sockets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "connections", entries); rrdset_done(st); } // -------------------------------------------------------------------- if(do_packets) { st = rrdset_find(RRD_TYPE_NET_IPVS ".packets"); if(!st) { st = rrdset_create(RRD_TYPE_NET_IPVS, "packets", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Packets", "packets/s", 1002, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "received", InPackets); rrddim_set(st, "sent", OutPackets); rrdset_done(st); } // -------------------------------------------------------------------- if(do_bandwidth) { st = rrdset_find(RRD_TYPE_NET_IPVS ".net"); if(!st) { st = rrdset_create(RRD_TYPE_NET_IPVS, "net", NULL, RRD_TYPE_NET_IPVS, NULL, "IPVS Bandwidth", "kilobits/s", 1000, update_every, RRDSET_TYPE_AREA); rrddim_add(st, "received", NULL, 8, 1024, RRDDIM_INCREMENTAL); rrddim_add(st, "sent", NULL, -8, 1024, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "received", InBytes); rrddim_set(st, "sent", OutBytes); rrdset_done(st); } return 0; }
int do_proc_net_rpc_nfs(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; static int do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1; static int proc2_warning = 0, proc3_warning = 0, proc4_warning = 0; 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); } 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 they are enabled, reset them to 1 // later we do them =2 to avoid doing strcmp() for all lines if(do_net) do_net = 1; if(do_rpc) do_rpc = 1; if(do_proc2) do_proc2 = 1; if(do_proc3) do_proc3 = 1; if(do_proc4) do_proc4 = 1; size_t lines = procfile_lines(ff), l; char *type; unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0; unsigned long long rpc_calls = 0, rpc_retransmits = 0, rpc_auth_refresh = 0; for(l = 0; l < lines ;l++) { size_t words = procfile_linewords(ff, l); if(!words) continue; type = procfile_lineword(ff, l, 0); if(do_net == 1 && strcmp(type, "net") == 0) { if(words < 5) { error("%s line of /proc/net/rpc/nfs has %zu words, expected %d", type, words, 5); continue; } net_count = str2ull(procfile_lineword(ff, l, 1)); net_udp_count = str2ull(procfile_lineword(ff, l, 2)); net_tcp_count = str2ull(procfile_lineword(ff, l, 3)); net_tcp_connections = str2ull(procfile_lineword(ff, l, 4)); unsigned long long sum = net_count + net_udp_count + net_tcp_count + net_tcp_connections; if(sum == 0ULL) do_net = -1; else do_net = 2; } else if(do_rpc == 1 && strcmp(type, "rpc") == 0) { if(words < 4) { error("%s line of /proc/net/rpc/nfs has %zu words, expected %d", type, words, 6); continue; } rpc_calls = str2ull(procfile_lineword(ff, l, 1)); rpc_retransmits = str2ull(procfile_lineword(ff, l, 2)); rpc_auth_refresh = str2ull(procfile_lineword(ff, l, 3)); unsigned long long sum = rpc_calls + rpc_retransmits + rpc_auth_refresh; if(sum == 0ULL) do_rpc = -1; else do_rpc = 2; } else if(do_proc2 == 1 && strcmp(type, "proc2") == 0) { // the first number is the count of numbers present // so we start for word 2 unsigned long long sum = 0; unsigned int i, j; for(i = 0, j = 2; j < words && nfs_proc2_values[i].name[0] ; i++, j++) { nfs_proc2_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfs_proc2_values[i].present = 1; sum += nfs_proc2_values[i].value; } if(sum == 0ULL) { if(!proc2_warning) { error("Disabling /proc/net/rpc/nfs v2 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it."); proc2_warning = 1; } do_proc2 = 0; } else do_proc2 = 2; } else if(do_proc3 == 1 && strcmp(type, "proc3") == 0) { // the first number is the count of numbers present // so we start for word 2 unsigned long long sum = 0; unsigned int i, j; for(i = 0, j = 2; j < words && nfs_proc3_values[i].name[0] ; i++, j++) { nfs_proc3_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfs_proc3_values[i].present = 1; sum += nfs_proc3_values[i].value; } if(sum == 0ULL) { if(!proc3_warning) { info("Disabling /proc/net/rpc/nfs v3 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it."); proc3_warning = 1; } do_proc3 = 0; } else do_proc3 = 2; } else if(do_proc4 == 1 && strcmp(type, "proc4") == 0) { // the first number is the count of numbers present // so we start for word 2 unsigned long long sum = 0; unsigned int i, j; for(i = 0, j = 2; j < words && nfs_proc4_values[i].name[0] ; i++, j++) { nfs_proc4_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfs_proc4_values[i].present = 1; sum += nfs_proc4_values[i].value; } if(sum == 0ULL) { if(!proc4_warning) { info("Disabling /proc/net/rpc/nfs v4 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it."); proc4_warning = 1; } do_proc4 = 0; } else do_proc4 = 2; } } // -------------------------------------------------------------------- if(do_net == 2) { static RRDSET *st = NULL; static RRDDIM *rd_udp = NULL, *rd_tcp = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "net" , NULL , "network" , NULL , "NFS Client Network" , "operations/s" , "proc" , "net/rpc/nfs" , 2207 , update_every , RRDSET_TYPE_STACKED ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rd_udp = rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_tcp = rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); // ignore net_count, net_tcp_connections (void)net_count; (void)net_tcp_connections; rrddim_set_by_pointer(st, rd_udp, net_udp_count); rrddim_set_by_pointer(st, rd_tcp, net_tcp_count); rrdset_done(st); } // -------------------------------------------------------------------- if(do_rpc == 2) { static RRDSET *st = NULL; static RRDDIM *rd_calls = NULL, *rd_retransmits = NULL, *rd_auth_refresh = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "rpc" , NULL , "rpc" , NULL , "NFS Client Remote Procedure Calls Statistics" , "calls/s" , "proc" , "net/rpc/nfs" , 2208 , update_every , RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rd_calls = rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_retransmits = rrddim_add(st, "retransmits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_auth_refresh = rrddim_add(st, "auth_refresh", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set_by_pointer(st, rd_calls, rpc_calls); rrddim_set_by_pointer(st, rd_retransmits, rpc_retransmits); rrddim_set_by_pointer(st, rd_auth_refresh, rpc_auth_refresh); rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc2 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "proc2" , NULL , "nfsv2rpc" , NULL , "NFS v2 Client Remote Procedure Calls" , "calls/s" , "proc" , "net/rpc/nfs" , 2209 , update_every , RRDSET_TYPE_STACKED ); } else rrdset_next(st); size_t i; for(i = 0; nfs_proc2_values[i].present ; i++) { if(unlikely(!nfs_proc2_values[i].rd)) nfs_proc2_values[i].rd = rrddim_add(st, nfs_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st, nfs_proc2_values[i].rd, nfs_proc2_values[i].value); } rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc3 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "proc3" , NULL , "nfsv3rpc" , NULL , "NFS v3 Client Remote Procedure Calls" , "calls/s" , "proc" , "net/rpc/nfs" , 2210 , update_every , RRDSET_TYPE_STACKED ); } else rrdset_next(st); size_t i; for(i = 0; nfs_proc3_values[i].present ; i++) { if(unlikely(!nfs_proc3_values[i].rd)) nfs_proc3_values[i].rd = rrddim_add(st, nfs_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st, nfs_proc3_values[i].rd, nfs_proc3_values[i].value); } rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc4 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "proc4" , NULL , "nfsv4rpc" , NULL , "NFS v4 Client Remote Procedure Calls" , "calls/s" , "proc" , "net/rpc/nfs" , 2211 , update_every , RRDSET_TYPE_STACKED ); } else rrdset_next(st); size_t i; for(i = 0; nfs_proc4_values[i].present ; i++) { if(unlikely(!nfs_proc4_values[i].rd)) nfs_proc4_values[i].rd = rrddim_add(st, nfs_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st, nfs_proc4_values[i].rd, nfs_proc4_values[i].value); } rrdset_done(st); } return 0; }
int main(int argc, char **argv) { int i; int config_loaded = 0; int dont_fork = 0; size_t wanted_stacksize = 0, stacksize = 0; pthread_attr_t attr; // global initialization get_HZ(); // set the name for logging program_name = "netdata"; // parse command line. // parse depercated options // TODO: Remove this block with the next major release. { i = 1; while(i < argc) { if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) { strncpyz(pidfile, argv[i+1], FILENAME_MAX); fprintf(stderr, "%s: deprecated option -- %s -- please use -P instead.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) { dont_fork = 1; fprintf(stderr, "%s: deprecated option -- %s -- please use -D instead.\n ", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { config_set("global", "host access prefix", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- please use -s instead.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set("global", "history", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- This option will be removed with V2.*.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else i++; } } // parse options { int num_opts = sizeof(options) / sizeof(struct option_def); char optstring[(num_opts * 2) + 1]; int string_i = 0; for( i = 0; i < num_opts; i++ ) { optstring[string_i] = options[i].val; string_i++; if(options[i].arg_name) { optstring[string_i] = ':'; string_i++; } } int opt; while( (opt = getopt(argc, argv, optstring)) != -1 ) { switch(opt) { case 'c': if(load_config(optarg, 1) != 1) { error("Cannot load configuration file %s.", optarg); exit(1); } else { debug(D_OPTIONS, "Configuration loaded from %s.", optarg); config_loaded = 1; } break; case 'D': dont_fork = 1; break; case 'h': help(0); break; case 'i': config_set("global", "bind to", optarg); break; case 'P': strncpy(pidfile, optarg, FILENAME_MAX); pidfile[FILENAME_MAX] = '\0'; break; case 'p': config_set("global", "default port", optarg); break; case 's': config_set("global", "host access prefix", optarg); break; case 't': config_set("global", "update every", optarg); break; case 'u': config_set("global", "run as user", optarg); break; case 'v': // TODO: Outsource version to makefile which can compute version from git. printf("netdata 1.2.1_master\n"); return 0; break; case 'W': { char* stacksize = "stacksize="; char* debug_flags_string = "debug_flags="; if(strcmp(optarg, "unittest") == 0) { rrd_update_every = 1; if(run_all_mockup_tests()) exit(1); if(unit_test_storage()) exit(1); fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); exit(0); } else if(strncmp(optarg, stacksize, strlen(stacksize)) == 0) { optarg += strlen(stacksize); config_set("global", "pthread stack size", optarg); } else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) { optarg += strlen(debug_flags_string); config_set("global", "debug flags", optarg); debug_flags = strtoull(optarg, NULL, 0); } } break; default: /* ? */ help(1); break; } } } if(!config_loaded) load_config(NULL, 0); // prepare configuration environment variables for the plugins setenv("NETDATA_CONFIG_DIR" , config_get("global", "config directory" , CONFIG_DIR) , 1); setenv("NETDATA_PLUGINS_DIR", config_get("global", "plugins directory" , PLUGINS_DIR), 1); setenv("NETDATA_WEB_DIR" , config_get("global", "web files directory", WEB_DIR) , 1); setenv("NETDATA_CACHE_DIR" , config_get("global", "cache directory" , CACHE_DIR) , 1); setenv("NETDATA_LIB_DIR" , config_get("global", "lib directory" , VARLIB_DIR) , 1); setenv("NETDATA_LOG_DIR" , config_get("global", "log directory" , LOG_DIR) , 1); setenv("NETDATA_HOST_PREFIX", config_get("global", "host access prefix" , "") , 1); setenv("HOME" , config_get("global", "home directory" , CACHE_DIR) , 1); // disable buffering for python plugins setenv("PYTHONUNBUFFERED", "1", 1); // avoid flood calls to stat(/etc/localtime) // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux setenv("TZ", ":/etc/localtime", 0); { char path[1024 + 1], *p = getenv("PATH"); if(!p) p = "/bin:/usr/bin"; snprintfz(path, 1024, "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin"); setenv("PATH", config_get("plugins", "PATH environment variable", path), 1); } // cd to /tmp to avoid any plugins writing files at random places if(chdir("/tmp")) error("netdata: ERROR: Cannot cd to /tmp"); char *input_log_file = NULL; char *output_log_file = NULL; char *error_log_file = NULL; char *access_log_file = NULL; char *user = NULL; { char *flags = config_get("global", "debug flags", "0x00000000"); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } // -------------------------------------------------------------------- #ifdef MADV_MERGEABLE enable_ksm = config_get_boolean("global", "memory deduplication (ksm)", enable_ksm); #else #warning "Kernel memory deduplication (KSM) is not available" #endif // -------------------------------------------------------------------- global_host_prefix = config_get("global", "host access prefix", ""); setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1); // -------------------------------------------------------------------- output_log_file = config_get("global", "debug log", LOG_DIR "/debug.log"); if(strcmp(output_log_file, "syslog") == 0) { output_log_syslog = 1; output_log_file = NULL; } else if(strcmp(output_log_file, "none") == 0) { output_log_syslog = 0; output_log_file = NULL; } else output_log_syslog = 0; // -------------------------------------------------------------------- error_log_file = config_get("global", "error log", LOG_DIR "/error.log"); if(strcmp(error_log_file, "syslog") == 0) { error_log_syslog = 1; error_log_file = NULL; } else if(strcmp(error_log_file, "none") == 0) { error_log_syslog = 0; error_log_file = NULL; // optimization - do not even generate debug log entries } else error_log_syslog = 0; error_log_throttle_period = config_get_number("global", "errors flood protection period", error_log_throttle_period); setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get("global", "errors flood protection period" , ""), 1); error_log_errors_per_period = (unsigned long)config_get_number("global", "errors to trigger flood protection", error_log_errors_per_period); setenv("NETDATA_ERRORS_PER_PERIOD" , config_get("global", "errors to trigger flood protection", ""), 1); // -------------------------------------------------------------------- access_log_file = config_get("global", "access log", LOG_DIR "/access.log"); if(strcmp(access_log_file, "syslog") == 0) { access_log_syslog = 1; access_log_file = NULL; } else if(strcmp(access_log_file, "none") == 0) { access_log_syslog = 0; access_log_file = NULL; } else access_log_syslog = 0; // -------------------------------------------------------------------- rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode))); // -------------------------------------------------------------------- { char hostnamebuf[HOSTNAME_MAX + 1]; if(gethostname(hostnamebuf, HOSTNAME_MAX) == -1) error("WARNING: Cannot get machine hostname."); hostname = config_get("global", "hostname", hostnamebuf); debug(D_OPTIONS, "hostname set to '%s'", hostname); } // -------------------------------------------------------------------- rrd_default_history_entries = (int) config_get_number("global", "history", RRD_DEFAULT_HISTORY_ENTRIES); if(rrd_default_history_entries < 5 || rrd_default_history_entries > RRD_HISTORY_ENTRIES_MAX) { info("Invalid save lines %d given. Defaulting to %d.", rrd_default_history_entries, RRD_DEFAULT_HISTORY_ENTRIES); rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; } else { debug(D_OPTIONS, "save lines set to %d.", rrd_default_history_entries); } // -------------------------------------------------------------------- rrd_update_every = (int) config_get_number("global", "update every", UPDATE_EVERY); if(rrd_update_every < 1 || rrd_update_every > 600) { info("Invalid update timer %d given. Defaulting to %d.", rrd_update_every, UPDATE_EVERY_MAX); rrd_update_every = UPDATE_EVERY; } else debug(D_OPTIONS, "update timer set to %d.", rrd_update_every); // let the plugins know the min update_every { char buf[16]; snprintfz(buf, 15, "%d", rrd_update_every); setenv("NETDATA_UPDATE_EVERY", buf, 1); } // -------------------------------------------------------------------- // block signals while initializing threads. // this causes the threads to block signals. sigset_t sigset; sigfillset(&sigset); if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) == -1) { error("Could not block signals for threads"); } // Catch signals which we want to use to quit savely struct sigaction sa; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGHUP); sigaddset(&sa.sa_mask, SIGINT); sigaddset(&sa.sa_mask, SIGTERM); sa.sa_handler = sig_handler_exit; sa.sa_flags = 0; if(sigaction(SIGHUP, &sa, NULL) == -1) { error("Failed to change signal handler for SIGHUP"); } if(sigaction(SIGINT, &sa, NULL) == -1) { error("Failed to change signal handler for SIGINT"); } if(sigaction(SIGTERM, &sa, NULL) == -1) { error("Failed to change signal handler for SIGTERM"); } // save database on SIGUSR1 sa.sa_handler = sig_handler_save; if(sigaction(SIGUSR1, &sa, NULL) == -1) { error("Failed to change signal handler for SIGUSR1"); } // Ignore SIGPIPE completely. // INFO: If we add signals here we have to unblock them // at popen.c when running a external plugin. sa.sa_handler = SIG_IGN; if(sigaction(SIGPIPE, &sa, NULL) == -1) { error("Failed to change signal handler for SIGPIPE"); } // -------------------------------------------------------------------- i = pthread_attr_init(&attr); if(i != 0) fatal("pthread_attr_init() failed with code %d.", i); i = pthread_attr_getstacksize(&attr, &stacksize); if(i != 0) fatal("pthread_attr_getstacksize() failed with code %d.", i); else debug(D_OPTIONS, "initial pthread stack size is %zu bytes", stacksize); wanted_stacksize = config_get_number("global", "pthread stack size", stacksize); // -------------------------------------------------------------------- for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); if(st->enabled && st->init_routine) st->init_routine(); } // -------------------------------------------------------------------- // get the user we should run // IMPORTANT: this is required before web_files_uid() user = config_get("global", "run as user" , (getuid() == 0)?NETDATA_USER:""); // IMPORTANT: these have to run once, while single threaded web_files_uid(); // IMPORTANT: web_files_uid() before web_files_gid() web_files_gid(); // -------------------------------------------------------------------- create_listen_sockets(); } // never become a problem if(nice(20) == -1) error("Cannot lower my CPU priority."); if(become_daemon(dont_fork, 0, user, input_log_file, output_log_file, error_log_file, access_log_file, &access_fd, &stdaccess) == -1) fatal("Cannot demonize myself."); #ifdef NETDATA_INTERNAL_CHECKS if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } #endif /* NETDATA_INTERNAL_CHECKS */ if(output_log_syslog || error_log_syslog || access_log_syslog) openlog("netdata", LOG_PID, LOG_DAEMON); info("NetData started on pid %d", getpid()); // ------------------------------------------------------------------------ // get default pthread stack size if(stacksize < wanted_stacksize) { i = pthread_attr_setstacksize(&attr, wanted_stacksize); if(i != 0) fatal("pthread_attr_setstacksize() to %zu bytes, failed with code %d.", wanted_stacksize, i); else info("Successfully set pthread stacksize to %zu bytes", wanted_stacksize); } // -------------------------------------------------------------------- // initialize the registry registry_init(); // ------------------------------------------------------------------------ // spawn the threads web_server_threading_selection(); for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->enabled) { st->thread = malloc(sizeof(pthread_t)); if(!st->thread) fatal("Cannot allocate pthread_t memory"); info("Starting thread %s.", st->name); if(pthread_create(st->thread, &attr, st->start_routine, NULL)) error("failed to create new thread for %s.", st->name); else if(pthread_detach(*st->thread)) error("Cannot request detach of newly created %s thread.", st->name); } else info("Not starting thread %s.", st->name); } // ------------------------------------------------------------------------ // block signals while initializing threads. sigset_t sigset; sigfillset(&sigset); if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1) { error("Could not unblock signals for threads"); } // Handle flags set in the signal handler. while(1) { pause(); if(netdata_exit) { info("Exit main loop of netdata."); netdata_cleanup_and_exit(0); exit(0); } } }
int main(int argc, char **argv) { int i; int config_loaded = 0; int dont_fork = 0; size_t default_stacksize; // set the name for logging program_name = "netdata"; // parse depercated options // TODO: Remove this block with the next major release. { i = 1; while(i < argc) { if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) { strncpyz(pidfile, argv[i+1], FILENAME_MAX); fprintf(stderr, "%s: deprecated option -- %s -- please use -P instead.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) { dont_fork = 1; fprintf(stderr, "%s: deprecated option -- %s -- please use -D instead.\n ", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { config_set(CONFIG_SECTION_GLOBAL, "host access prefix", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- please use -s instead.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set(CONFIG_SECTION_GLOBAL, "history", argv[i+1]); fprintf(stderr, "%s: deprecated option -- %s -- This option will be removed with V2.*.\n", argv[0], argv[i]); remove_option(i, &argc, argv); } else i++; } } // parse options { int num_opts = sizeof(option_definitions) / sizeof(struct option_def); char optstring[(num_opts * 2) + 1]; int string_i = 0; for( i = 0; i < num_opts; i++ ) { optstring[string_i] = option_definitions[i].val; string_i++; if(option_definitions[i].arg_name) { optstring[string_i] = ':'; string_i++; } } // terminate optstring optstring[string_i] ='\0'; optstring[(num_opts *2)] ='\0'; int opt; while( (opt = getopt(argc, argv, optstring)) != -1 ) { switch(opt) { case 'c': if(config_load(optarg, 1) != 1) { error("Cannot load configuration file %s.", optarg); return 1; } else { debug(D_OPTIONS, "Configuration loaded from %s.", optarg); config_loaded = 1; } break; case 'D': dont_fork = 1; break; case 'h': return help(0); case 'i': config_set(CONFIG_SECTION_WEB, "bind to", optarg); break; case 'P': strncpy(pidfile, optarg, FILENAME_MAX); pidfile[FILENAME_MAX] = '\0'; break; case 'p': config_set(CONFIG_SECTION_GLOBAL, "default port", optarg); break; case 's': config_set(CONFIG_SECTION_GLOBAL, "host access prefix", optarg); break; case 't': config_set(CONFIG_SECTION_GLOBAL, "update every", optarg); break; case 'u': config_set(CONFIG_SECTION_GLOBAL, "run as user", optarg); break; case 'v': case 'V': printf("%s %s\n", program_name, program_version); return 0; case 'W': { char* stacksize_string = "stacksize="; char* debug_flags_string = "debug_flags="; 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; default_health_enabled = 0; rrd_init("unittest"); default_rrdpush_enabled = 0; if(run_all_mockup_tests()) return 1; if(unit_test_storage()) return 1; fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); return 0; } else if(strcmp(optarg, "simple-pattern") == 0) { if(optind + 2 > argc) { fprintf(stderr, "%s", "\nUSAGE: -W simple-pattern 'pattern' 'string'\n\n" " Checks if 'pattern' matches the given 'string'.\n" " - 'pattern' can be one or more space separated words.\n" " - each 'word' can contain one or more asterisks.\n" " - words starting with '!' give negative matches.\n" " - words are processed left to right\n" "\n" "Examples:\n" "\n" " > match all veth interfaces, except veth0:\n" "\n" " -W simple-pattern '!veth0 veth*' 'veth12'\n" "\n" "\n" " > match all *.ext files directly in /path/:\n" " (this will not match *.ext files in a subdir of /path/)\n" "\n" " -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n" "\n" ); return 1; } const char *heystack = argv[optind]; const char *needle = argv[optind + 1]; size_t len = strlen(needle) + 1; char wildcarded[len]; SIMPLE_PATTERN *p = simple_pattern_create(heystack, NULL, SIMPLE_PATTERN_EXACT); int ret = simple_pattern_matches_extract(p, needle, wildcarded, len); simple_pattern_free(p); if(ret) { fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s', wildcarded '%s'\n", heystack, needle, wildcarded); return 0; } else { fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s', wildcarded '%s'\n", heystack, needle, wildcarded); return 1; } } else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) { optarg += strlen(stacksize_string); config_set(CONFIG_SECTION_GLOBAL, "pthread stack size", optarg); } else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) { optarg += strlen(debug_flags_string); config_set(CONFIG_SECTION_GLOBAL, "debug flags", optarg); debug_flags = strtoull(optarg, NULL, 0); } else if(strcmp(optarg, "set") == 0) { if(optind + 3 > argc) { fprintf(stderr, "%s", "\nUSAGE: -W set 'section' 'key' 'value'\n\n" " Overwrites settings of netdata.conf.\n" "\n" " These options interact with: -c netdata.conf\n" " If -c netdata.conf is given on the command line,\n" " before -W set... the user may overwrite command\n" " line parameters at netdata.conf\n" " If -c netdata.conf is given after (or missing)\n" " -W set... the user cannot overwrite the command line\n" " parameters." "\n" ); return 1; } const char *section = argv[optind]; const char *key = argv[optind + 1]; const char *value = argv[optind + 2]; optind += 3; // set this one as the default // only if it is not already set in the config file // so the caller can use -c netdata.conf before or // after this parameter to prevent or allow overwriting // variables at netdata.conf config_set_default(section, key, value); // fprintf(stderr, "SET section '%s', key '%s', value '%s'\n", section, key, value); } else if(strcmp(optarg, "get") == 0) { if(optind + 3 > argc) { fprintf(stderr, "%s", "\nUSAGE: -W get 'section' 'key' 'value'\n\n" " Prints settings of netdata.conf.\n" "\n" " These options interact with: -c netdata.conf\n" " -c netdata.conf has to be given before -W get.\n" "\n" ); return 1; } 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); } backwards_compatible_config(); get_netdata_configured_variables(); const char *section = argv[optind]; const char *key = argv[optind + 1]; const char *def = argv[optind + 2]; const char *value = config_get(section, key, def); printf("%s\n", value); return 0; } else { fprintf(stderr, "Unknown -W parameter '%s'\n", optarg); return help(1); } } break; default: /* ? */ fprintf(stderr, "Unknown parameter '%c'\n", opt); return help(1); } } } #ifdef _SC_OPEN_MAX // close all open file descriptors, except the standard ones // the caller may have left open files (lxc-attach has this issue) { int fd; for(fd = (int) (sysconf(_SC_OPEN_MAX) - 1); fd > 2; fd--) if(fd_is_valid(fd)) close(fd); } #endif if(!config_loaded) config_load(NULL, 0); // ------------------------------------------------------------------------ // initialize netdata { char *pmax = config_get(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for plugins", "1"); if(pmax && *pmax) setenv("MALLOC_ARENA_MAX", pmax, 1); #if defined(HAVE_C_MALLOPT) i = (int)config_get_number(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for netdata", 1); if(i > 0) mallopt(M_ARENA_MAX, 1); #endif // prepare configuration environment variables for the plugins get_netdata_configured_variables(); set_global_environment(); // 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); } char *user = NULL; { // -------------------------------------------------------------------- // get the debugging flags from the configuration file char *flags = config_get(CONFIG_SECTION_GLOBAL, "debug flags", "0x0000000000000000"); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); debug(D_OPTIONS, "Debug flags set to '0x%" PRIX64 "'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) error("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); #ifdef HAVE_SYS_PRCTL_H prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); #endif } // -------------------------------------------------------------------- // get log filenames and settings log_init(); error_log_limit_unlimited(); // -------------------------------------------------------------------- // 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. // this causes the threads to block signals. signals_block(); // setup the signals we want to use signals_init(); // setup threads configs default_stacksize = netdata_threads_init(); // -------------------------------------------------------------------- // check which threads are enabled and initialize them for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); if(st->enabled && st->init_routine) st->init_routine(); } // -------------------------------------------------------------------- // get the user we should run // IMPORTANT: this is required before web_files_uid() if(getuid() == 0) { user = config_get(CONFIG_SECTION_GLOBAL, "run as user", NETDATA_USER); } else { struct passwd *passwd = getpwuid(getuid()); user = config_get(CONFIG_SECTION_GLOBAL, "run as user", (passwd && passwd->pw_name)?passwd->pw_name:""); } // -------------------------------------------------------------------- // create the listening sockets web_client_api_v1_init(); web_server_threading_selection(); if(web_server_mode != WEB_SERVER_MODE_NONE) api_listen_sockets_setup(); } // initialize the log files open_all_log_files(); #ifdef NETDATA_INTERNAL_CHECKS if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) error("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); #ifdef HAVE_SYS_PRCTL_H prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); #endif } #endif /* NETDATA_INTERNAL_CHECKS */ // get the max file limit 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); // fork, switch user, create pid file, set process priority if(become_daemon(dont_fork, user) == -1) fatal("Cannot daemonize myself."); info("netdata started on pid %d.", getpid()); // IMPORTANT: these have to run once, while single threaded // but after we have switched user web_files_uid(); web_files_gid(); netdata_threads_init_after_fork((size_t)config_get_number(CONFIG_SECTION_GLOBAL, "pthread stack size", (long)default_stacksize)); // ------------------------------------------------------------------------ // initialize rrd, registry, health, rrdpush, etc. rrd_init(netdata_configured_hostname); // ------------------------------------------------------------------------ // enable log flood protection error_log_limit_reset(); // ------------------------------------------------------------------------ // spawn the threads web_server_config_options(); for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->enabled) { st->thread = mallocz(sizeof(netdata_thread_t)); debug(D_SYSTEM, "Starting thread %s.", st->name); netdata_thread_create(st->thread, st->name, NETDATA_THREAD_OPTION_DEFAULT, st->start_routine, st); } else debug(D_SYSTEM, "Not starting thread %s.", st->name); } info("netdata initialization completed. Enjoy real-time performance monitoring!"); // ------------------------------------------------------------------------ // unblock signals signals_unblock(); // ------------------------------------------------------------------------ // Handle signals signals_handle(); // should never reach this point // but we need it for rpmlint #2752 return 1; }
int do_proc_vmstat(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; static int do_swapio = -1, do_io = -1, do_pgfaults = -1, do_numa = -1; static int has_numa = -1; static ARL_BASE *arl_base = NULL; static unsigned long long numa_foreign = 0ULL; static unsigned long long numa_hint_faults = 0ULL; static unsigned long long numa_hint_faults_local = 0ULL; static unsigned long long numa_huge_pte_updates = 0ULL; static unsigned long long numa_interleave = 0ULL; static unsigned long long numa_local = 0ULL; static unsigned long long numa_other = 0ULL; static unsigned long long numa_pages_migrated = 0ULL; static unsigned long long numa_pte_updates = 0ULL; static unsigned long long pgfault = 0ULL; static unsigned long long pgmajfault = 0ULL; static unsigned long long pgpgin = 0ULL; static unsigned long long pgpgout = 0ULL; static unsigned long long pswpin = 0ULL; static unsigned long long pswpout = 0ULL; if(unlikely(!arl_base)) { do_swapio = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "swap i/o", CONFIG_BOOLEAN_AUTO); do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1); do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1); do_numa = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "system-wide numa metric summary", CONFIG_BOOLEAN_AUTO); arl_base = arl_create("vmstat", NULL, 60); arl_expect(arl_base, "pgfault", &pgfault); arl_expect(arl_base, "pgmajfault", &pgmajfault); arl_expect(arl_base, "pgpgin", &pgpgin); arl_expect(arl_base, "pgpgout", &pgpgout); arl_expect(arl_base, "pswpin", &pswpin); arl_expect(arl_base, "pswpout", &pswpout); if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && get_numa_node_count() >= 2)) { arl_expect(arl_base, "numa_foreign", &numa_foreign); arl_expect(arl_base, "numa_hint_faults_local", &numa_hint_faults_local); arl_expect(arl_base, "numa_hint_faults", &numa_hint_faults); arl_expect(arl_base, "numa_huge_pte_updates", &numa_huge_pte_updates); arl_expect(arl_base, "numa_interleave", &numa_interleave); arl_expect(arl_base, "numa_local", &numa_local); arl_expect(arl_base, "numa_other", &numa_other); arl_expect(arl_base, "numa_pages_migrated", &numa_pages_migrated); arl_expect(arl_base, "numa_pte_updates", &numa_pte_updates); } else { // Do not expect numa metrics when they are not needed. // By not adding them, the ARL will stop processing the file // when all the expected metrics are collected. // Also ARL will not parse their values. has_numa = 0; do_numa = CONFIG_BOOLEAN_NO; } } if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/vmstat"); ff = procfile_open(config_get("plugin:proc:/proc/vmstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return 1; } ff = procfile_readall(ff); if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time size_t lines = procfile_lines(ff), l; arl_begin(arl_base); for(l = 0; l < lines ;l++) { size_t words = procfile_linewords(ff, l); if(unlikely(words < 2)) { if(unlikely(words)) error("Cannot read /proc/vmstat line %zu. Expected 2 params, read %zu.", l, words); continue; } if(unlikely(arl_check(arl_base, procfile_lineword(ff, l, 0), procfile_lineword(ff, l, 1)))) break; } // -------------------------------------------------------------------- if(pswpin || pswpout || do_swapio == CONFIG_BOOLEAN_YES) { do_swapio = CONFIG_BOOLEAN_YES; static RRDSET *st_swapio = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; if(unlikely(!st_swapio)) { st_swapio = rrdset_create_localhost( "system" , "swapio" , NULL , "swap" , NULL , "Swap I/O" , "kilobytes/s" , 250 , update_every , RRDSET_TYPE_AREA ); rd_in = rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_swapio); rrddim_set_by_pointer(st_swapio, rd_in, pswpin); rrddim_set_by_pointer(st_swapio, rd_out, pswpout); rrdset_done(st_swapio); } // -------------------------------------------------------------------- if(do_io) { static RRDSET *st_io = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; if(unlikely(!st_io)) { st_io = rrdset_create_localhost( "system" , "io" , NULL , "disk" , NULL , "Disk I/O" , "kilobytes/s" , 150 , update_every , RRDSET_TYPE_AREA ); rd_in = rrddim_add(st_io, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st_io, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_io); rrddim_set_by_pointer(st_io, rd_in, pgpgin); rrddim_set_by_pointer(st_io, rd_out, pgpgout); rrdset_done(st_io); } // -------------------------------------------------------------------- if(do_pgfaults) { static RRDSET *st_pgfaults = NULL; static RRDDIM *rd_minor = NULL, *rd_major = NULL; if(unlikely(!st_pgfaults)) { st_pgfaults = rrdset_create_localhost( "mem" , "pgfaults" , NULL , "system" , NULL , "Memory Page Faults" , "page faults/s" , 500 , update_every , RRDSET_TYPE_LINE ); rrdset_flag_set(st_pgfaults, RRDSET_FLAG_DETAIL); rd_minor = rrddim_add(st_pgfaults, "minor", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_major = rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_pgfaults); rrddim_set_by_pointer(st_pgfaults, rd_minor, pgfault); rrddim_set_by_pointer(st_pgfaults, rd_major, pgmajfault); rrdset_done(st_pgfaults); } // -------------------------------------------------------------------- // Ondemand criteria for NUMA. Since this won't change at run time, we // check it only once. We check whether the node count is >= 2 because // single-node systems have uninteresting statistics (since all accesses // are local). if(unlikely(has_numa == -1)) has_numa = (numa_local || numa_foreign || numa_interleave || numa_other || numa_pte_updates || numa_huge_pte_updates || numa_hint_faults || numa_hint_faults_local || numa_pages_migrated) ? 1 : 0; if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && has_numa)) { do_numa = CONFIG_BOOLEAN_YES; static RRDSET *st_numa = NULL; static RRDDIM *rd_local = NULL, *rd_foreign = NULL, *rd_interleave = NULL, *rd_other = NULL, *rd_pte_updates = NULL, *rd_huge_pte_updates = NULL, *rd_hint_faults = NULL, *rd_hint_faults_local = NULL, *rd_pages_migrated = NULL; if(unlikely(!st_numa)) { st_numa = rrdset_create_localhost( "mem" , "numa" , NULL , "numa" , NULL , "NUMA events" , "events/s" , 800 , update_every , RRDSET_TYPE_LINE ); rrdset_flag_set(st_numa, RRDSET_FLAG_DETAIL); // These depend on CONFIG_NUMA in the kernel. rd_local = rrddim_add(st_numa, "local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_foreign = rrddim_add(st_numa, "foreign", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_interleave = rrddim_add(st_numa, "interleave", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_other = rrddim_add(st_numa, "other", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); // The following stats depend on CONFIG_NUMA_BALANCING in the // kernel. rd_pte_updates = rrddim_add(st_numa, "pte_updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_huge_pte_updates = rrddim_add(st_numa, "huge_pte_updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_hint_faults = rrddim_add(st_numa, "hint_faults", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_hint_faults_local = rrddim_add(st_numa, "hint_faults_local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_pages_migrated = rrddim_add(st_numa, "pages_migrated", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_numa); rrddim_set_by_pointer(st_numa, rd_local, numa_local); rrddim_set_by_pointer(st_numa, rd_foreign, numa_foreign); rrddim_set_by_pointer(st_numa, rd_interleave, numa_interleave); rrddim_set_by_pointer(st_numa, rd_other, numa_other); rrddim_set_by_pointer(st_numa, rd_pte_updates, numa_pte_updates); rrddim_set_by_pointer(st_numa, rd_huge_pte_updates, numa_huge_pte_updates); rrddim_set_by_pointer(st_numa, rd_hint_faults, numa_hint_faults); rrddim_set_by_pointer(st_numa, rd_hint_faults_local, numa_hint_faults_local); rrddim_set_by_pointer(st_numa, rd_pages_migrated, numa_pages_migrated); rrdset_done(st_numa); } return 0; }
int main(int argc, char **argv) { int i; int config_loaded = 0; int dont_fork = 0; size_t wanted_stacksize = 0, stacksize = 0; pthread_attr_t attr; // global initialization get_HZ(); // set the name for logging program_name = "netdata"; // parse the arguments for(i = 1; i < argc ; i++) { if(strcmp(argv[i], "-c") == 0 && (i+1) < argc) { if(load_config(argv[i+1], 1) != 1) { error("Cannot load configuration file %s.", argv[i+1]); exit(1); } else { debug(D_OPTIONS, "Configuration loaded from %s.", argv[i+1]); config_loaded = 1; } i++; } else if(strcmp(argv[i], "-df") == 0 && (i+1) < argc) { config_set("global", "debug flags", argv[i+1]); debug_flags = strtoull(argv[i+1], NULL, 0); i++; } else if(strcmp(argv[i], "-p") == 0 && (i+1) < argc) { config_set("global", "port", argv[i+1]); i++; } else if(strcmp(argv[i], "-u") == 0 && (i+1) < argc) { config_set("global", "run as user", argv[i+1]); i++; } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set("global", "history", argv[i+1]); i++; } else if(strcmp(argv[i], "-t") == 0 && (i+1) < argc) { config_set("global", "update every", argv[i+1]); i++; } else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { config_set("global", "host access prefix", argv[i+1]); i++; } else if(strcmp(argv[i], "-stacksize") == 0 && (i+1) < argc) { config_set("global", "pthread stack size", argv[i+1]); i++; } else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) dont_fork = 1; else if(strcmp(argv[i], "-pidfile") == 0 && (i+1) < argc) { i++; strncpy(pidfile, argv[i], FILENAME_MAX); pidfile[FILENAME_MAX] = '\0'; } else if(strcmp(argv[i], "--unittest") == 0) { rrd_update_every = 1; if(run_all_mockup_tests()) exit(1); if(unit_test_storage()) exit(1); fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); exit(0); } else { fprintf(stderr, "Cannot understand option '%s'.\n", argv[i]); fprintf(stderr, "\nUSAGE: %s [-d] [-l LINES_TO_SAVE] [-u UPDATE_TIMER] [-p LISTEN_PORT] [-df debug flags].\n\n", argv[0]); fprintf(stderr, " -c CONFIG FILE the configuration file to load. Default: %s.\n", CONFIG_DIR "/" CONFIG_FILENAME); fprintf(stderr, " -l LINES_TO_SAVE can be from 5 to %d lines in JSON data. Default: %d.\n", RRD_HISTORY_ENTRIES_MAX, RRD_DEFAULT_HISTORY_ENTRIES); fprintf(stderr, " -t UPDATE_TIMER can be from 1 to %d seconds. Default: %d.\n", UPDATE_EVERY_MAX, UPDATE_EVERY); fprintf(stderr, " -p LISTEN_PORT can be from 1 to %d. Default: %d.\n", 65535, LISTEN_PORT); fprintf(stderr, " -u USERNAME can be any system username to run as. Default: none.\n"); fprintf(stderr, " -ch path to access host /proc and /sys when running in a container. Default: empty.\n"); fprintf(stderr, " -nd or -nodeamon to disable forking in the background. Default: unset.\n"); fprintf(stderr, " -df FLAGS debug options. Default: 0x%08llx.\n", debug_flags); fprintf(stderr, " -stacksize BYTES to overwrite the pthread stack size.\n"); fprintf(stderr, " -pidfile FILENAME to save a pid while running.\n"); exit(1); } } if(!config_loaded) load_config(NULL, 0); // prepare configuration environment variables for the plugins setenv("NETDATA_CONFIG_DIR" , config_get("global", "config directory" , CONFIG_DIR) , 1); setenv("NETDATA_PLUGINS_DIR", config_get("global", "plugins directory" , PLUGINS_DIR), 1); setenv("NETDATA_WEB_DIR" , config_get("global", "web files directory", WEB_DIR) , 1); setenv("NETDATA_CACHE_DIR" , config_get("global", "cache directory" , CACHE_DIR) , 1); setenv("NETDATA_LOG_DIR" , config_get("global", "log directory" , LOG_DIR) , 1); setenv("NETDATA_HOST_PREFIX", config_get("global", "host access prefix" , "") , 1); setenv("HOME" , config_get("global", "home directory" , CACHE_DIR) , 1); // avoid extended to stat(/etc/localtime) // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux setenv("TZ", ":/etc/localtime", 0); // cd to /tmp to avoid any plugins writing files at random places if(chdir("/tmp")) error("netdata: ERROR: Cannot cd to /tmp"); char *input_log_file = NULL; char *output_log_file = NULL; char *error_log_file = NULL; char *access_log_file = NULL; char *user = NULL; { char buffer[1024]; // -------------------------------------------------------------------- sprintf(buffer, "0x%08llx", 0ULL); char *flags = config_get("global", "debug flags", buffer); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } // -------------------------------------------------------------------- #ifdef MADV_MERGEABLE enable_ksm = config_get_boolean("global", "memory deduplication (ksm)", enable_ksm); #else #warning "Kernel memory deduplication (KSM) is not available" #endif // -------------------------------------------------------------------- global_host_prefix = config_get("global", "host access prefix", ""); setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1); // -------------------------------------------------------------------- output_log_file = config_get("global", "debug log", LOG_DIR "/debug.log"); if(strcmp(output_log_file, "syslog") == 0) { output_log_syslog = 1; output_log_file = NULL; } else if(strcmp(output_log_file, "none") == 0) { output_log_syslog = 0; output_log_file = NULL; } else output_log_syslog = 0; // -------------------------------------------------------------------- error_log_file = config_get("global", "error log", LOG_DIR "/error.log"); if(strcmp(error_log_file, "syslog") == 0) { error_log_syslog = 1; error_log_file = NULL; } else if(strcmp(error_log_file, "none") == 0) { error_log_syslog = 0; error_log_file = NULL; // optimization - do not even generate debug log entries } else error_log_syslog = 0; error_log_throttle_period = config_get_number("global", "errors flood protection period", error_log_throttle_period); setenv("NETDATA_ERRORS_THROTTLE_PERIOD", config_get("global", "errors flood protection period" , ""), 1); error_log_errors_per_period = config_get_number("global", "errors to trigger flood protection", error_log_errors_per_period); setenv("NETDATA_ERRORS_PER_PERIOD" , config_get("global", "errors to trigger flood protection", ""), 1); // -------------------------------------------------------------------- access_log_file = config_get("global", "access log", LOG_DIR "/access.log"); if(strcmp(access_log_file, "syslog") == 0) { access_log_syslog = 1; access_log_file = NULL; } else if(strcmp(access_log_file, "none") == 0) { access_log_syslog = 0; access_log_file = NULL; } else access_log_syslog = 0; // -------------------------------------------------------------------- rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode))); // -------------------------------------------------------------------- if(gethostname(buffer, HOSTNAME_MAX) == -1) error("WARNING: Cannot get machine hostname."); hostname = config_get("global", "hostname", buffer); debug(D_OPTIONS, "hostname set to '%s'", hostname); // -------------------------------------------------------------------- rrd_default_history_entries = (int) config_get_number("global", "history", RRD_DEFAULT_HISTORY_ENTRIES); if(rrd_default_history_entries < 5 || rrd_default_history_entries > RRD_HISTORY_ENTRIES_MAX) { info("Invalid save lines %d given. Defaulting to %d.", rrd_default_history_entries, RRD_DEFAULT_HISTORY_ENTRIES); rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; } else { debug(D_OPTIONS, "save lines set to %d.", rrd_default_history_entries); } // -------------------------------------------------------------------- rrd_update_every = (int) config_get_number("global", "update every", UPDATE_EVERY); if(rrd_update_every < 1 || rrd_update_every > 600) { info("Invalid update timer %d given. Defaulting to %d.", rrd_update_every, UPDATE_EVERY_MAX); rrd_update_every = UPDATE_EVERY; } else debug(D_OPTIONS, "update timer set to %d.", rrd_update_every); // let the plugins know the min update_every { char buf[50]; snprintf(buf, 50, "%d", rrd_update_every); setenv("NETDATA_UPDATE_EVERY", buf, 1); } // -------------------------------------------------------------------- // block signals while initializing threads. // this causes the threads to block signals. sigset_t sigset; sigfillset(&sigset); if(pthread_sigmask(SIG_BLOCK, &sigset, NULL) == -1) { error("Could not block signals for threads"); } // Catch signals which we want to use to quit savely struct sigaction sa; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGHUP); sigaddset(&sa.sa_mask, SIGINT); sigaddset(&sa.sa_mask, SIGTERM); sa.sa_handler = sig_handler; sa.sa_flags = 0; if(sigaction(SIGHUP, &sa, NULL) == -1) { error("Failed to change signal handler for SIGHUP"); } if(sigaction(SIGINT, &sa, NULL) == -1) { error("Failed to change signal handler for SIGINT"); } if(sigaction(SIGTERM, &sa, NULL) == -1) { error("Failed to change signal handler for SIGTERM"); } // Ignore SIGPIPE completely. // INFO: If we add signals here we have to unblock them // at popen.c when running a external plugin. sa.sa_handler = SIG_IGN; if(sigaction(SIGPIPE, &sa, NULL) == -1) { error("Failed to change signal handler for SIGTERM"); } // -------------------------------------------------------------------- i = pthread_attr_init(&attr); if(i != 0) fatal("pthread_attr_init() failed with code %d.", i); i = pthread_attr_getstacksize(&attr, &stacksize); if(i != 0) fatal("pthread_attr_getstacksize() failed with code %d.", i); else debug(D_OPTIONS, "initial pthread stack size is %zu bytes", stacksize); wanted_stacksize = config_get_number("global", "pthread stack size", stacksize); // -------------------------------------------------------------------- for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); if(st->enabled && st->init_routine) st->init_routine(); } // -------------------------------------------------------------------- // get the user we should run // IMPORTANT: this is required before web_files_uid() user = config_get("global", "run as user" , (getuid() == 0)?NETDATA_USER:""); // IMPORTANT: these have to run once, while single threaded web_files_uid(); // IMPORTANT: web_files_uid() before web_files_gid() web_files_gid(); // -------------------------------------------------------------------- listen_backlog = (int) config_get_number("global", "http port listen backlog", LISTEN_BACKLOG); listen_port = (int) config_get_number("global", "port", LISTEN_PORT); if(listen_port < 1 || listen_port > 65535) { info("Invalid listen port %d given. Defaulting to %d.", listen_port, LISTEN_PORT); listen_port = LISTEN_PORT; } else debug(D_OPTIONS, "Listen port set to %d.", listen_port); int ip = 0; char *ipv = config_get("global", "ip version", "any"); if(!strcmp(ipv, "any") || !strcmp(ipv, "both") || !strcmp(ipv, "all")) ip = 0; else if(!strcmp(ipv, "ipv4") || !strcmp(ipv, "IPV4") || !strcmp(ipv, "IPv4") || !strcmp(ipv, "4")) ip = 4; else if(!strcmp(ipv, "ipv6") || !strcmp(ipv, "IPV6") || !strcmp(ipv, "IPv6") || !strcmp(ipv, "6")) ip = 6; else info("Cannot understand ip version '%s'. Assuming 'any'.", ipv); if(ip == 0 || ip == 6) listen_fd = create_listen_socket6(config_get("global", "bind socket to IP", "*"), listen_port, listen_backlog); if(listen_fd < 0) { listen_fd = create_listen_socket4(config_get("global", "bind socket to IP", "*"), listen_port, listen_backlog); if(listen_fd >= 0 && ip != 4) info("Managed to open an IPv4 socket on port %d.", listen_port); } if(listen_fd < 0) fatal("Cannot listen socket."); } // never become a problem if(nice(20) == -1) error("Cannot lower my CPU priority."); if(become_daemon(dont_fork, 0, user, input_log_file, output_log_file, error_log_file, access_log_file, &access_fd, &stdaccess) == -1) { fatal("Cannot demonize myself."); exit(1); } if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } if(output_log_syslog || error_log_syslog || access_log_syslog) openlog("netdata", LOG_PID, LOG_DAEMON); info("NetData started on pid %d", getpid()); // ------------------------------------------------------------------------ // get default pthread stack size if(stacksize < wanted_stacksize) { i = pthread_attr_setstacksize(&attr, wanted_stacksize); if(i != 0) fatal("pthread_attr_setstacksize() to %zu bytes, failed with code %d.", wanted_stacksize, i); else info("Successfully set pthread stacksize to %zu bytes", wanted_stacksize); } // ------------------------------------------------------------------------ // spawn the threads for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->enabled) { st->thread = malloc(sizeof(pthread_t)); if(!st->thread) fatal("Cannot allocate pthread_t memory"); info("Starting thread %s.", st->name); if(pthread_create(st->thread, &attr, st->start_routine, NULL)) error("failed to create new thread for %s.", st->name); else if(pthread_detach(*st->thread)) error("Cannot request detach of newly created %s thread.", st->name); } else info("Not starting thread %s.", st->name); } // ------------------------------------------------------------------------ // block signals while initializing threads. sigset_t sigset; sigfillset(&sigset); if(pthread_sigmask(SIG_UNBLOCK, &sigset, NULL) == -1) { error("Could not unblock signals for threads"); } // Handle flags set in the signal handler. while(1) { pause(); if(netdata_exit) { info("Exit main loop of netdata."); netdata_cleanup_and_exit(0); exit(0); } } }
int main(int argc, char **argv) { int i; int config_loaded = 0; int dont_fork = 0; // global initialization get_HZ(); // set the name for logging program_name = "netdata"; // parse the arguments for(i = 1; i < argc ; i++) { if(strcmp(argv[i], "-c") == 0 && (i+1) < argc) { if(load_config(argv[i+1], 1) != 1) { error("Cannot load configuration file %s.", argv[i+1]); exit(1); } else { debug(D_OPTIONS, "Configuration loaded from %s.", argv[i+1]); config_loaded = 1; } i++; } else if(strcmp(argv[i], "-df") == 0 && (i+1) < argc) { config_set("global", "debug flags", argv[i+1]); debug_flags = strtoull(argv[i+1], NULL, 0); i++; } else if(strcmp(argv[i], "-p") == 0 && (i+1) < argc) { config_set("global", "port", argv[i+1]); i++; } else if(strcmp(argv[i], "-u") == 0 && (i+1) < argc) { config_set("global", "run as user", argv[i+1]); i++; } else if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) { config_set("global", "history", argv[i+1]); i++; } else if(strcmp(argv[i], "-t") == 0 && (i+1) < argc) { config_set("global", "update every", argv[i+1]); i++; } else if(strcmp(argv[i], "-ch") == 0 && (i+1) < argc) { config_set("global", "host access prefix", argv[i+1]); i++; } else if(strcmp(argv[i], "-nodaemon") == 0 || strcmp(argv[i], "-nd") == 0) dont_fork = 1; else if(strcmp(argv[i], "--unittest") == 0) { rrd_update_every = 1; if(run_all_mockup_tests()) exit(1); if(unit_test_storage()) exit(1); fprintf(stderr, "\n\nALL TESTS PASSED\n\n"); exit(0); } else { fprintf(stderr, "Cannot understand option '%s'.\n", argv[i]); fprintf(stderr, "\nUSAGE: %s [-d] [-l LINES_TO_SAVE] [-u UPDATE_TIMER] [-p LISTEN_PORT] [-df debug flags].\n\n", argv[0]); fprintf(stderr, " -c CONFIG FILE the configuration file to load. Default: %s.\n", CONFIG_DIR "/" CONFIG_FILENAME); fprintf(stderr, " -l LINES_TO_SAVE can be from 5 to %d lines in JSON data. Default: %d.\n", RRD_HISTORY_ENTRIES_MAX, RRD_DEFAULT_HISTORY_ENTRIES); fprintf(stderr, " -t UPDATE_TIMER can be from 1 to %d seconds. Default: %d.\n", UPDATE_EVERY_MAX, UPDATE_EVERY); fprintf(stderr, " -p LISTEN_PORT can be from 1 to %d. Default: %d.\n", 65535, LISTEN_PORT); fprintf(stderr, " -u USERNAME can be any system username to run as. Default: none.\n"); fprintf(stderr, " -ch path to access host /proc and /sys when running in a container. Default: empty.\n"); fprintf(stderr, " -nd or -nodeamon to disable forking in the background. Default: unset.\n"); fprintf(stderr, " -df FLAGS debug options. Default: 0x%08llx.\n", debug_flags); exit(1); } } if(!config_loaded) load_config(NULL, 0); // prepare configuration environment variables for the plugins setenv("NETDATA_CONFIG_DIR" , config_get("global", "config directory" , CONFIG_DIR) , 1); setenv("NETDATA_PLUGINS_DIR", config_get("global", "plugins directory" , PLUGINS_DIR), 1); setenv("NETDATA_WEB_DIR" , config_get("global", "web files directory", WEB_DIR) , 1); setenv("NETDATA_CACHE_DIR" , config_get("global", "cache directory" , CACHE_DIR) , 1); setenv("NETDATA_LOG_DIR" , config_get("global", "log directory" , LOG_DIR) , 1); setenv("NETDATA_HOST_PREFIX", config_get("global", "host access prefix" , "") , 1); // avoid extended to stat(/etc/localtime) // http://stackoverflow.com/questions/4554271/how-to-avoid-excessive-stat-etc-localtime-calls-in-strftime-on-linux setenv("TZ", ":/etc/localtime", 0); // cd to /tmp to avoid any plugins writing files at random places if(chdir("/tmp")) error("netdata: ERROR: Cannot cd to /tmp"); char *input_log_file = NULL; char *output_log_file = NULL; char *error_log_file = NULL; char *access_log_file = NULL; char *user = NULL; { char buffer[1024]; // -------------------------------------------------------------------- sprintf(buffer, "0x%08llx", 0ULL); char *flags = config_get("global", "debug flags", buffer); setenv("NETDATA_DEBUG_FLAGS", flags, 1); debug_flags = strtoull(flags, NULL, 0); debug(D_OPTIONS, "Debug flags set to '0x%8llx'.", debug_flags); if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } // -------------------------------------------------------------------- #ifdef MADV_MERGEABLE enable_ksm = config_get_boolean("global", "memory deduplication (ksm)", enable_ksm); #else #warning "Kernel memory deduplication (KSM) is not available" #endif // -------------------------------------------------------------------- global_host_prefix = config_get("global", "host access prefix", ""); setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1); // -------------------------------------------------------------------- output_log_file = config_get("global", "debug log", LOG_DIR "/debug.log"); if(strcmp(output_log_file, "syslog") == 0) { output_log_syslog = 1; output_log_file = NULL; } else if(strcmp(output_log_file, "none") == 0) { output_log_syslog = 0; output_log_file = NULL; } else output_log_syslog = 0; // -------------------------------------------------------------------- error_log_file = config_get("global", "error log", LOG_DIR "/error.log"); if(strcmp(error_log_file, "syslog") == 0) { error_log_syslog = 1; error_log_file = NULL; } else if(strcmp(error_log_file, "none") == 0) { error_log_syslog = 0; error_log_file = NULL; // optimization - do not even generate debug log entries } else error_log_syslog = 0; // -------------------------------------------------------------------- access_log_file = config_get("global", "access log", LOG_DIR "/access.log"); if(strcmp(access_log_file, "syslog") == 0) { access_log_syslog = 1; access_log_file = NULL; } else if(strcmp(access_log_file, "none") == 0) { access_log_syslog = 0; access_log_file = NULL; } else access_log_syslog = 0; // -------------------------------------------------------------------- rrd_memory_mode = rrd_memory_mode_id(config_get("global", "memory mode", rrd_memory_mode_name(rrd_memory_mode))); // -------------------------------------------------------------------- if(gethostname(buffer, HOSTNAME_MAX) == -1) error("WARNING: Cannot get machine hostname."); hostname = config_get("global", "hostname", buffer); debug(D_OPTIONS, "hostname set to '%s'", hostname); // -------------------------------------------------------------------- rrd_default_history_entries = (int) config_get_number("global", "history", RRD_DEFAULT_HISTORY_ENTRIES); if(rrd_default_history_entries < 5 || rrd_default_history_entries > RRD_HISTORY_ENTRIES_MAX) { fprintf(stderr, "Invalid save lines %d given. Defaulting to %d.\n", rrd_default_history_entries, RRD_DEFAULT_HISTORY_ENTRIES); rrd_default_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; } else { debug(D_OPTIONS, "save lines set to %d.", rrd_default_history_entries); } // -------------------------------------------------------------------- rrd_update_every = (int) config_get_number("global", "update every", UPDATE_EVERY); if(rrd_update_every < 1 || rrd_update_every > 600) { fprintf(stderr, "Invalid update timer %d given. Defaulting to %d.\n", rrd_update_every, UPDATE_EVERY_MAX); rrd_update_every = UPDATE_EVERY; } else debug(D_OPTIONS, "update timer set to %d.", rrd_update_every); // let the plugins know the min update_every { char buf[50]; snprintf(buf, 50, "%d", rrd_update_every); setenv("NETDATA_UPDATE_EVERY", buf, 1); } // -------------------------------------------------------------------- for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->config_name) st->enabled = config_get_boolean(st->config_section, st->config_name, st->enabled); if(st->enabled && st->init_routine) st->init_routine(); } // -------------------------------------------------------------------- prepare_rundir(); user = config_get("global", "run as user" , (getuid() == 0)?NETDATA_USER:""); web_files_uid(); // -------------------------------------------------------------------- listen_backlog = (int) config_get_number("global", "http port listen backlog", LISTEN_BACKLOG); listen_port = (int) config_get_number("global", "port", LISTEN_PORT); if(listen_port < 1 || listen_port > 65535) { fprintf(stderr, "Invalid listen port %d given. Defaulting to %d.\n", listen_port, LISTEN_PORT); listen_port = LISTEN_PORT; } else debug(D_OPTIONS, "Listen port set to %d.", listen_port); int ip = 0; char *ipv = config_get("global", "ip version", "any"); if(!strcmp(ipv, "any") || !strcmp(ipv, "both") || !strcmp(ipv, "all")) ip = 0; else if(!strcmp(ipv, "ipv4") || !strcmp(ipv, "IPV4") || !strcmp(ipv, "IPv4") || !strcmp(ipv, "4")) ip = 4; else if(!strcmp(ipv, "ipv6") || !strcmp(ipv, "IPV6") || !strcmp(ipv, "IPv6") || !strcmp(ipv, "6")) ip = 6; else fprintf(stderr, "Cannot understand ip version '%s'. Assumming 'any'.", ipv); if(ip == 0 || ip == 6) listen_fd = create_listen_socket6(listen_port, listen_backlog); if(listen_fd < 0) { listen_fd = create_listen_socket4(listen_port, listen_backlog); if(listen_fd >= 0 && ip != 4) fprintf(stderr, "Managed to open an IPv4 socket on port %d.", listen_port); } if(listen_fd < 0) fatal("Cannot listen socket."); } // never become a problem if(nice(20) == -1) error("Cannot lower my CPU priority."); if(become_daemon(dont_fork, 0, user, input_log_file, output_log_file, error_log_file, access_log_file, &access_fd, &stdaccess) == -1) { fatal("Cannot demonize myself."); exit(1); } if(debug_flags != 0) { struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if(setrlimit(RLIMIT_CORE, &rl) != 0) info("Cannot request unlimited core dumps for debugging... Proceeding anyway..."); prctl(PR_SET_DUMPABLE, 1, 0, 0, 0); } if(output_log_syslog || error_log_syslog || access_log_syslog) openlog("netdata", LOG_PID, LOG_DAEMON); info("NetData started on pid %d", getpid()); // catch all signals for (i = 1 ; i < 65 ;i++) { switch(i) { case SIGKILL: // not catchable case SIGSTOP: // not catchable break; case SIGSEGV: case SIGFPE: case SIGCHLD: signal(i, SIG_DFL); break; default: signal(i, sig_handler); break; } } for (i = 0; static_threads[i].name != NULL ; i++) { struct netdata_static_thread *st = &static_threads[i]; if(st->enabled) { st->thread = malloc(sizeof(pthread_t)); if(!st->thread) fatal("Cannot allocate pthread_t memory"); info("Starting thread %s.", st->name); if(pthread_create(st->thread, NULL, st->start_routine, NULL)) error("failed to create new thread for %s.", st->name); else if(pthread_detach(*st->thread)) error("Cannot request detach of newly created %s thread.", st->name); } else info("Not starting thread %s.", st->name); } // for future use - the main thread while(1) { if(netdata_exit != 0) { netdata_exit++; if(netdata_exit > 5) { netdata_cleanup_and_exit(0); exit(0); } } sleep(2); } exit(0); }
int do_sys_class_power_supply(int update_every, usec_t dt) { (void)dt; static int do_capacity = -1, do_property[3] = {-1}; static int keep_fds_open = CONFIG_BOOLEAN_NO, keep_fds_open_config = -1; static char *dirname = NULL; if(unlikely(do_capacity == -1)) { do_capacity = config_get_boolean("plugin:proc:/sys/class/power_supply", "battery capacity", CONFIG_BOOLEAN_YES); do_property[0] = config_get_boolean("plugin:proc:/sys/class/power_supply", "battery charge", CONFIG_BOOLEAN_NO); do_property[1] = config_get_boolean("plugin:proc:/sys/class/power_supply", "battery energy", CONFIG_BOOLEAN_NO); do_property[2] = config_get_boolean("plugin:proc:/sys/class/power_supply", "power supply voltage", CONFIG_BOOLEAN_NO); keep_fds_open_config = config_get_boolean_ondemand("plugin:proc:/sys/class/power_supply", "keep files open", CONFIG_BOOLEAN_AUTO); char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/class/power_supply"); dirname = config_get("plugin:proc:/sys/class/power_supply", "directory to monitor", filename); } DIR *dir = opendir(dirname); if(unlikely(!dir)) { error("Cannot read directory '%s'", dirname); return 1; } struct dirent *de = NULL; while(likely(de = readdir(dir))) { if(likely(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') ))) continue; if(likely(de->d_type == DT_LNK || de->d_type == DT_DIR)) { uint32_t hash = simple_hash(de->d_name); struct power_supply *ps; for(ps = power_supply_root; ps; ps = ps->next) { if(unlikely(ps->hash == hash && !strcmp(ps->name, de->d_name))) { ps->found = 1; break; } } // allocate memory for power supply and initialize it if(unlikely(!ps)) { ps = callocz(sizeof(struct power_supply), 1); ps->name = strdupz(de->d_name); ps->hash = simple_hash(de->d_name); ps->found = 1; ps->next = power_supply_root; power_supply_root = ps; struct stat stbuf; if(likely(do_capacity != CONFIG_BOOLEAN_NO)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/%s/%s", dirname, de->d_name, "capacity"); if (stat(filename, &stbuf) == 0) { ps->capacity = callocz(sizeof(struct capacity), 1); ps->capacity->filename = strdupz(filename); ps->capacity->fd = -1; files_num++; } } // allocate memory and initialize structures for every property and file found size_t pr_idx, pd_idx; size_t prev_idx = 3; // there is no property with this index for(pr_idx = 0; pr_idx < 3; pr_idx++) { if(unlikely(do_property[pr_idx] != CONFIG_BOOLEAN_NO)) { struct ps_property *pr = NULL; for(pd_idx = pr_idx * 5; pd_idx < pr_idx * 5 + 5; pd_idx++) { // check if file exists char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/%s/%s_%s", dirname, de->d_name, ps_property_names[pr_idx], ps_property_dim_names[pd_idx]); if (stat(filename, &stbuf) == 0) { // add chart if(unlikely(prev_idx != pr_idx)) { pr = callocz(sizeof(struct ps_property), 1); pr->name = strdupz(ps_property_names[pr_idx]); pr->title = strdupz(ps_property_titles[pr_idx]); pr->units = strdupz(ps_property_units[pr_idx]); prev_idx = pr_idx; pr->next = ps->property_root; ps->property_root = pr; } // add dimension struct ps_property_dim *pd; pd= callocz(sizeof(struct ps_property_dim), 1); pd->name = strdupz(ps_property_dim_names[pd_idx]); pd->filename = strdupz(filename); pd->fd = -1; files_num++; pd->next = pr->property_dim_root; pr->property_dim_root = pd; } } } } } // read capacity file if(likely(ps->capacity)) { char buffer[30 + 1]; if(unlikely(ps->capacity->fd == -1)) { ps->capacity->fd = open(ps->capacity->filename, O_RDONLY, 0666); if(unlikely(ps->capacity->fd == -1)) { error("Cannot open file '%s'", ps->capacity->filename); power_supply_free(ps); } } ssize_t r = read(ps->capacity->fd, buffer, 30); if(unlikely(r < 1)) { error("Cannot read file '%s'", ps->capacity->filename); power_supply_free(ps); } else { buffer[r] = '\0'; ps->capacity->value = str2ull(buffer); } if(unlikely(!keep_fds_open)) { close(ps->capacity->fd); ps->capacity->fd = -1; } else if(unlikely(lseek(ps->capacity->fd, 0, SEEK_SET) == -1)) { error("Cannot seek in file '%s'", ps->capacity->filename); close(ps->capacity->fd); ps->capacity->fd = -1; } } // read property files int read_error = 0; struct ps_property *pr; for(pr = ps->property_root; pr && !read_error; pr = pr->next) { struct ps_property_dim *pd; for(pd = pr->property_dim_root; pd; pd = pd->next) { char buffer[30 + 1]; if(unlikely(pd->fd == -1)) { pd->fd = open(pd->filename, O_RDONLY, 0666); if(unlikely(pd->fd == -1)) { error("Cannot open file '%s'", pd->filename); read_error = 1; power_supply_free(ps); break; } } ssize_t r = read(pd->fd, buffer, 30); if(unlikely(r < 1)) { error("Cannot read file '%s'", pd->filename); read_error = 1; power_supply_free(ps); break; } buffer[r] = '\0'; pd->value = str2ull(buffer); if(unlikely(!keep_fds_open)) { close(pd->fd); pd->fd = -1; } else if(unlikely(lseek(pd->fd, 0, SEEK_SET) == -1)) { error("Cannot seek in file '%s'", pd->filename); close(pd->fd); pd->fd = -1; } } } } } closedir(dir); keep_fds_open = keep_fds_open_config; if(likely(keep_fds_open_config == CONFIG_BOOLEAN_AUTO)) { if(unlikely(files_num > 32)) keep_fds_open = CONFIG_BOOLEAN_NO; else keep_fds_open = CONFIG_BOOLEAN_YES; } // -------------------------------------------------------------------- struct power_supply *ps = power_supply_root; while(unlikely(ps)) { if(unlikely(!ps->found)) { struct power_supply *f = ps; ps = ps->next; power_supply_free(f); continue; } if(likely(ps->capacity)) { if(unlikely(!ps->capacity->st)) { ps->capacity->st = rrdset_create_localhost( "powersupply_capacity" , ps->name , NULL , ps->name , "powersupply.capacity" , "Battery capacity" , "percentage" , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_POWER_SUPPLY_NAME , NETDATA_CHART_PRIO_POWER_SUPPLY_CAPACITY , update_every , RRDSET_TYPE_LINE ); } else rrdset_next(ps->capacity->st); if(unlikely(!ps->capacity->rd)) ps->capacity->rd = rrddim_add(ps->capacity->st, "capacity", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(ps->capacity->st, ps->capacity->rd, ps->capacity->value); rrdset_done(ps->capacity->st); } struct ps_property *pr; for(pr = ps->property_root; pr; pr = pr->next) { if(unlikely(!pr->st)) { char id[RRD_ID_LENGTH_MAX + 1], context[RRD_ID_LENGTH_MAX + 1]; snprintfz(id, RRD_ID_LENGTH_MAX, "powersupply_%s", pr->name); snprintfz(context, RRD_ID_LENGTH_MAX, "powersupply.%s", pr->name); pr->st = rrdset_create_localhost( id , ps->name , NULL , ps->name , context , pr->title , pr->units , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_POWER_SUPPLY_NAME , NETDATA_CHART_PRIO_POWER_SUPPLY_CAPACITY , update_every , RRDSET_TYPE_LINE ); } else rrdset_next(pr->st); struct ps_property_dim *pd; for(pd = pr->property_dim_root; pd; pd = pd->next) { if(unlikely(!pd->rd)) pd->rd = rrddim_add(pr->st, pd->name, NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(pr->st, pd->rd, pd->value); } rrdset_done(pr->st); } ps->found = 0; ps = ps->next; } return 0; }
void *proc_main(void *ptr) { if(ptr) { ; } if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) error("Cannot set pthread cancel type to DEFERRED."); if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("Cannot set pthread cancel state to ENABLE."); struct rusage me, me_last; struct timeval last, now; gettimeofday(&last, NULL); last.tv_sec -= rrd_update_every; // disable (by default) various interface that are not needed config_get_boolean("plugin:proc:/proc/net/dev", "interface lo", 0); config_get_boolean("plugin:proc:/proc/net/dev", "interface fireqos_monitor", 0); // when ZERO, attempt to do it int vdo_proc_net_dev = !config_get_boolean("plugin:proc", "/proc/net/dev", 1); int vdo_proc_diskstats = !config_get_boolean("plugin:proc", "/proc/diskstats", 1); int vdo_proc_net_snmp = !config_get_boolean("plugin:proc", "/proc/net/snmp", 1); int vdo_proc_net_netstat = !config_get_boolean("plugin:proc", "/proc/net/netstat", 1); int vdo_proc_net_stat_conntrack = !config_get_boolean("plugin:proc", "/proc/net/stat/conntrack", 1); int vdo_proc_net_ip_vs_stats = !config_get_boolean("plugin:proc", "/proc/net/ip_vs/stats", 1); int vdo_proc_stat = !config_get_boolean("plugin:proc", "/proc/stat", 1); int vdo_proc_meminfo = !config_get_boolean("plugin:proc", "/proc/meminfo", 1); int vdo_proc_vmstat = !config_get_boolean("plugin:proc", "/proc/vmstat", 1); int vdo_proc_net_rpc_nfsd = !config_get_boolean("plugin:proc", "/proc/net/rpc/nfsd", 1); int vdo_proc_sys_kernel_random_entropy_avail = !config_get_boolean("plugin:proc", "/proc/sys/kernel/random/entropy_avail", 1); int vdo_proc_interrupts = !config_get_boolean("plugin:proc", "/proc/interrupts", 1); int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1); RRDSET *stcpu = NULL, *stclients = NULL, *streqs = NULL, *stbytes = NULL; gettimeofday(&last, NULL); getrusage(RUSAGE_SELF, &me_last); unsigned long long usec = 0, susec = 0; for(;1;) { // BEGIN -- the job to be done if(!vdo_proc_interrupts) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts()."); vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, usec+susec); } if(!vdo_proc_sys_kernel_random_entropy_avail) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail()."); vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, usec+susec); } if(!vdo_proc_net_dev) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev()."); vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, usec+susec); } if(!vdo_proc_diskstats) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats()."); vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, usec+susec); } if(!vdo_proc_net_snmp) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp()."); vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, usec+susec); } if(!vdo_proc_net_netstat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat()."); vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, usec+susec); } if(!vdo_proc_net_stat_conntrack) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack()."); vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, usec+susec); } if(!vdo_proc_net_ip_vs_stats) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats()."); vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, usec+susec); } if(!vdo_proc_stat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat()."); vdo_proc_stat = do_proc_stat(rrd_update_every, usec+susec); } if(!vdo_proc_meminfo) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo()."); vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, usec+susec); } if(!vdo_proc_vmstat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat()."); vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, usec+susec); } if(!vdo_proc_net_rpc_nfsd) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd()."); vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, usec+susec); } // END -- the job is done // find the time to sleep in order to wait exactly update_every seconds gettimeofday(&now, NULL); usec = usecdiff(&now, &last) - susec; debug(D_PROCNETDEV_LOOP, "PROCNETDEV: last loop took %llu usec (worked for %llu, sleeped for %llu).", usec + susec, usec, susec); if(usec < (rrd_update_every * 1000000ULL / 2ULL)) susec = (rrd_update_every * 1000000ULL) - usec; else susec = rrd_update_every * 1000000ULL / 2ULL; // -------------------------------------------------------------------- if(!vdo_cpu_netdata && getrusage(RUSAGE_SELF, &me) == 0) { unsigned long long cpuuser = me.ru_utime.tv_sec * 1000000ULL + me.ru_utime.tv_usec; unsigned long long cpusyst = me.ru_stime.tv_sec * 1000000ULL + me.ru_stime.tv_usec; if(!stcpu) stcpu = rrdset_find("netdata.server_cpu"); if(!stcpu) { stcpu = rrdset_create("netdata", "server_cpu", NULL, "netdata", "NetData CPU usage", "milliseconds/s", 9999, rrd_update_every, RRDSET_TYPE_STACKED); rrddim_add(stcpu, "user", NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL); rrddim_add(stcpu, "system", NULL, 1, 1000 * rrd_update_every, RRDDIM_INCREMENTAL); } else rrdset_next(stcpu); rrddim_set(stcpu, "user", cpuuser); rrddim_set(stcpu, "system", cpusyst); rrdset_done(stcpu); bcopy(&me, &me_last, sizeof(struct rusage)); // ---------------------------------------------------------------- if(!stclients) stclients = rrdset_find("netdata.clients"); if(!stclients) { stclients = rrdset_create("netdata", "clients", NULL, "netdata", "NetData Web Clients", "connected clients", 11000, rrd_update_every, RRDSET_TYPE_LINE); rrddim_add(stclients, "clients", NULL, 1, 1, RRDDIM_ABSOLUTE); } else rrdset_next(stclients); rrddim_set(stclients, "clients", global_statistics.connected_clients); rrdset_done(stclients); // ---------------------------------------------------------------- if(!streqs) streqs = rrdset_find("netdata.requests"); if(!streqs) { streqs = rrdset_create("netdata", "requests", NULL, "netdata", "NetData Web Requests", "requests/s", 12000, rrd_update_every, RRDSET_TYPE_LINE); rrddim_add(streqs, "requests", NULL, 1, 1 * rrd_update_every, RRDDIM_INCREMENTAL); } else rrdset_next(streqs); rrddim_set(streqs, "requests", global_statistics.web_requests); rrdset_done(streqs); // ---------------------------------------------------------------- if(!stbytes) stbytes = rrdset_find("netdata.net"); if(!stbytes) { stbytes = rrdset_create("netdata", "net", NULL, "netdata", "NetData Network Traffic", "kilobits/s", 13000, rrd_update_every, RRDSET_TYPE_AREA); rrddim_add(stbytes, "in", NULL, 8, 1024 * rrd_update_every, RRDDIM_INCREMENTAL); rrddim_add(stbytes, "out", NULL, -8, 1024 * rrd_update_every, RRDDIM_INCREMENTAL); } else rrdset_next(stbytes); rrddim_set(stbytes, "in", global_statistics.bytes_received); rrddim_set(stbytes, "out", global_statistics.bytes_sent); rrdset_done(stbytes); } usleep(susec); // copy current to last bcopy(&now, &last, sizeof(struct timeval)); } return NULL; }
void *proc_diskspace_main(void *ptr) { struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; info("DISKSPACE thread created with task id %d", gettid()); if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) error("DISKSPACE: Cannot set pthread cancel type to DEFERRED."); if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("DISKSPACE: Cannot set pthread cancel state to ENABLE."); int vdo_cpu_netdata = config_get_boolean("plugin:proc", "netdata server resources", 1); int update_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "update every", localhost->rrd_update_every); if(update_every < localhost->rrd_update_every) update_every = localhost->rrd_update_every; check_for_new_mountpoints_every = (int)config_get_number(CONFIG_SECTION_DISKSPACE, "check for new mount points every", check_for_new_mountpoints_every); if(check_for_new_mountpoints_every < update_every) check_for_new_mountpoints_every = update_every; struct rusage thread; usec_t duration = 0; usec_t step = update_every * USEC_PER_SEC; heartbeat_t hb; heartbeat_init(&hb); for(;;) { duration = heartbeat_dt_usec(&hb); /* usec_t hb_dt = */ heartbeat_next(&hb, step); if(unlikely(netdata_exit)) break; // -------------------------------------------------------------------------- // this is smart enough not to reload it every time mountinfo_reload(0); // -------------------------------------------------------------------------- // disk space metrics struct mountinfo *mi; for(mi = disk_mountinfo_root; mi; mi = mi->next) { if(unlikely(mi->flags & (MOUNTINFO_IS_DUMMY | MOUNTINFO_IS_BIND))) continue; do_disk_space_stats(mi, update_every); if(unlikely(netdata_exit)) break; } if(unlikely(netdata_exit)) break; dictionary_get_all(dict_mountpoints, mount_point_cleanup, NULL); if(vdo_cpu_netdata) { static RRDSET *stcpu_thread = NULL, *st_duration = NULL; static RRDDIM *rd_user = NULL, *rd_system = NULL, *rd_duration = NULL; // ---------------------------------------------------------------- getrusage(RUSAGE_THREAD, &thread); if(!stcpu_thread) { stcpu_thread = rrdset_find_localhost("netdata.plugin_diskspace"); if(!stcpu_thread) stcpu_thread = rrdset_create_localhost( "netdata" , "plugin_diskspace" , NULL , "diskspace" , NULL , "NetData Disk Space Plugin CPU usage" , "milliseconds/s" , 132020 , update_every , RRDSET_TYPE_STACKED ); rd_user = rrddim_add(stcpu_thread, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); rd_system = rrddim_add(stcpu_thread, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(stcpu_thread); rrddim_set_by_pointer(stcpu_thread, rd_user, thread.ru_utime.tv_sec * 1000000ULL + thread.ru_utime.tv_usec); rrddim_set_by_pointer(stcpu_thread, rd_system, thread.ru_stime.tv_sec * 1000000ULL + thread.ru_stime.tv_usec); rrdset_done(stcpu_thread); // ---------------------------------------------------------------- if(!st_duration) { st_duration = rrdset_find_localhost("netdata.plugin_diskspace_dt"); if(!st_duration) st_duration = rrdset_create_localhost( "netdata" , "plugin_diskspace_dt" , NULL , "diskspace" , NULL , "NetData Disk Space Plugin Duration" , "milliseconds/run" , 132021 , update_every , RRDSET_TYPE_AREA ); rd_duration = rrddim_add(st_duration, "duration", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st_duration); rrddim_set_by_pointer(st_duration, rd_duration, duration); rrdset_done(st_duration); // ---------------------------------------------------------------- if(unlikely(netdata_exit)) break; } } info("DISKSPACE thread exiting"); static_thread->enabled = 0; pthread_exit(NULL); return NULL; }
RRDSET *rrdset_create(const char *type, const char *id, const char *name, const char *family, const char *context, const char *title, const char *units, long priority, int update_every, int chart_type) { if(!type || !type[0]) { fatal("Cannot create rrd stats without a type."); return NULL; } if(!id || !id[0]) { fatal("Cannot create rrd stats without an id."); return NULL; } char fullid[RRD_ID_LENGTH_MAX + 1]; char fullfilename[FILENAME_MAX + 1]; RRDSET *st = NULL; snprintfz(fullid, RRD_ID_LENGTH_MAX, "%s.%s", type, id); st = rrdset_find(fullid); if(st) { error("Cannot create rrd stats for '%s', it already exists.", fullid); return st; } long entries = config_get_number(fullid, "history", rrd_default_history_entries); if(entries < 5) entries = config_set_number(fullid, "history", 5); if(entries > RRD_HISTORY_ENTRIES_MAX) entries = config_set_number(fullid, "history", RRD_HISTORY_ENTRIES_MAX); int enabled = config_get_boolean(fullid, "enabled", 1); if(!enabled) entries = 5; unsigned long size = sizeof(RRDSET); char *cache_dir = rrdset_cache_dir(fullid); debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id); snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir); if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0); if(st) { if(strcmp(st->magic, RRDSET_MAGIC) != 0) { errno = 0; info("Initializing file %s.", fullfilename); bzero(st, size); } else if(strcmp(st->id, fullid) != 0) { errno = 0; error("File %s contents are not for chart %s. Clearing it.", fullfilename, fullid); // munmap(st, size); // st = NULL; bzero(st, size); } else if(st->memsize != size || st->entries != entries) { errno = 0; error("File %s does not have the desired size. Clearing it.", fullfilename); bzero(st, size); } else if(st->update_every != update_every) { errno = 0; error("File %s does not have the desired update frequency. Clearing it.", fullfilename); bzero(st, size); } else if((time(NULL) - st->last_updated.tv_sec) > update_every * entries) { errno = 0; error("File %s is too old. Clearing it.", fullfilename); bzero(st, size); } } if(st) { st->name = NULL; st->type = NULL; st->family = NULL; st->context = NULL; st->title = NULL; st->units = NULL; st->dimensions = NULL; st->next = NULL; st->mapped = rrd_memory_mode; } else { st = calloc(1, size); if(!st) { fatal("Cannot allocate memory for RRD_STATS %s.%s", type, id); return NULL; } st->mapped = RRD_MEMORY_MODE_RAM; } st->memsize = size; st->entries = entries; st->update_every = update_every; if(st->current_entry >= st->entries) st->current_entry = 0; strcpy(st->cache_filename, fullfilename); strcpy(st->magic, RRDSET_MAGIC); strcpy(st->id, fullid); st->hash = simple_hash(st->id); st->cache_dir = cache_dir; st->chart_type = rrdset_type_id(config_get(st->id, "chart type", rrdset_type_name(chart_type))); st->type = config_get(st->id, "type", type); st->family = config_get(st->id, "family", family?family:st->type); st->context = config_get(st->id, "context", context?context:st->id); st->units = config_get(st->id, "units", units?units:""); st->priority = config_get_number(st->id, "priority", priority); st->enabled = enabled; st->isdetail = 0; st->debug = 0; st->last_collected_time.tv_sec = 0; st->last_collected_time.tv_usec = 0; st->counter_done = 0; st->gap_when_lost_iterations_above = (int) ( config_get_number(st->id, "gap when lost iterations above", RRD_DEFAULT_GAP_INTERPOLATIONS) + 2); avl_init_lock(&st->dimensions_index, rrddim_compare); pthread_rwlock_init(&st->rwlock, NULL); pthread_rwlock_wrlock(&rrdset_root_rwlock); if(name && *name) rrdset_set_name(st, name); else rrdset_set_name(st, id); { char varvalue[CONFIG_MAX_VALUE + 1]; snprintfz(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name); st->title = config_get(st->id, "title", varvalue); } st->next = rrdset_root; rrdset_root = st; rrdset_index_add(st); pthread_rwlock_unlock(&rrdset_root_rwlock); return(st); }
int do_proc_net_stat_conntrack(int update_every, unsigned long long dt) { static procfile *ff = NULL; static int do_sockets = -1, do_new = -1, do_changes = -1, do_expect = -1, do_search = -1, do_errors = -1; if(do_sockets == -1) do_sockets = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connections", 1); if(do_new == -1) do_new = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter new connections", 1); if(do_changes == -1) do_changes = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection changes", 1); if(do_expect == -1) do_expect = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection expectations", 1); if(do_search == -1) do_search = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter connection searches", 1); if(do_errors == -1) do_errors = config_get_boolean("plugin:proc:/proc/net/stat/nf_conntrack", "netfilter errors", 1); if(dt) {}; if(!ff) { char filename[FILENAME_MAX + 1]; snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/nf_conntrack"); ff = procfile_open(config_get("plugin:proc:/proc/net/stat/nf_conntrack", "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 uint32_t lines = procfile_lines(ff), l; uint32_t words; unsigned long long aentries = 0, asearched = 0, afound = 0, anew = 0, ainvalid = 0, aignore = 0, adelete = 0, adelete_list = 0, ainsert = 0, ainsert_failed = 0, adrop = 0, aearly_drop = 0, aicmp_error = 0, aexpect_new = 0, aexpect_create = 0, aexpect_delete = 0, asearch_restart = 0; for(l = 1; l < lines ;l++) { words = procfile_linewords(ff, l); if(words < 17) { if(words) error("Cannot read /proc/net/stat/nf_conntrack line. Expected 17 params, read %d.", words); continue; } unsigned long long tentries = 0, tsearched = 0, tfound = 0, tnew = 0, tinvalid = 0, tignore = 0, tdelete = 0, tdelete_list = 0, tinsert = 0, tinsert_failed = 0, tdrop = 0, tearly_drop = 0, ticmp_error = 0, texpect_new = 0, texpect_create = 0, texpect_delete = 0, tsearch_restart = 0; tentries = strtoull(procfile_lineword(ff, l, 0), NULL, 16); tsearched = strtoull(procfile_lineword(ff, l, 1), NULL, 16); tfound = strtoull(procfile_lineword(ff, l, 2), NULL, 16); tnew = strtoull(procfile_lineword(ff, l, 3), NULL, 16); tinvalid = strtoull(procfile_lineword(ff, l, 4), NULL, 16); tignore = strtoull(procfile_lineword(ff, l, 5), NULL, 16); tdelete = strtoull(procfile_lineword(ff, l, 6), NULL, 16); tdelete_list = strtoull(procfile_lineword(ff, l, 7), NULL, 16); tinsert = strtoull(procfile_lineword(ff, l, 8), NULL, 16); tinsert_failed = strtoull(procfile_lineword(ff, l, 9), NULL, 16); tdrop = strtoull(procfile_lineword(ff, l, 10), NULL, 16); tearly_drop = strtoull(procfile_lineword(ff, l, 11), NULL, 16); ticmp_error = strtoull(procfile_lineword(ff, l, 12), NULL, 16); texpect_new = strtoull(procfile_lineword(ff, l, 13), NULL, 16); texpect_create = strtoull(procfile_lineword(ff, l, 14), NULL, 16); texpect_delete = strtoull(procfile_lineword(ff, l, 15), NULL, 16); tsearch_restart = strtoull(procfile_lineword(ff, l, 16), NULL, 16); if(!aentries) aentries = tentries; // sum all the cpus together asearched += tsearched; // conntrack.search afound += tfound; // conntrack.search anew += tnew; // conntrack.new ainvalid += tinvalid; // conntrack.new aignore += tignore; // conntrack.new adelete += tdelete; // conntrack.changes adelete_list += tdelete_list; // conntrack.changes ainsert += tinsert; // conntrack.changes ainsert_failed += tinsert_failed; // conntrack.errors adrop += tdrop; // conntrack.errors aearly_drop += tearly_drop; // conntrack.errors aicmp_error += ticmp_error; // conntrack.errors aexpect_new += texpect_new; // conntrack.expect aexpect_create += texpect_create; // conntrack.expect aexpect_delete += texpect_delete; // conntrack.expect asearch_restart += tsearch_restart; // conntrack.search } RRDSET *st; // -------------------------------------------------------------------- if(do_sockets) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_sockets"); if(!st) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_sockets", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Connections", "active connections", 1000, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "connections", NULL, 1, 1, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "connections", aentries); rrdset_done(st); } // -------------------------------------------------------------------- if(do_new) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_new"); if(!st) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_new", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker New Connections", "connections/s", 1001, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "ignore", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "new", anew); rrddim_set(st, "ignore", aignore); rrddim_set(st, "invalid", ainvalid); rrdset_done(st); } // -------------------------------------------------------------------- if(do_changes) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_changes"); if(!st) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_changes", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Changes", "changes/s", 1002, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "inserted", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "delete_list", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "inserted", ainsert); rrddim_set(st, "deleted", adelete); rrddim_set(st, "delete_list", adelete_list); rrdset_done(st); } // -------------------------------------------------------------------- if(do_expect) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_expect"); if(!st) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_expect", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Expectations", "expectations/s", 1003, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "created", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "deleted", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "new", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "created", aexpect_create); rrddim_set(st, "deleted", aexpect_delete); rrddim_set(st, "new", aexpect_new); rrdset_done(st); } // -------------------------------------------------------------------- if(do_search) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_search"); if(!st) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_search", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Searches", "searches/s", 1010, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "searched", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "restarted", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "found", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "searched", asearched); rrddim_set(st, "restarted", asearch_restart); rrddim_set(st, "found", afound); rrdset_done(st); } // -------------------------------------------------------------------- if(do_errors) { st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_CONNTRACK "_errors"); if(!st) { st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_CONNTRACK "_errors", NULL, RRD_TYPE_NET_STAT_CONNTRACK, NULL, "Connection Tracker Errors", "events/s", 1005, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "icmp_error", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "insert_failed", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "drop", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "early_drop", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "icmp_error", aicmp_error); rrddim_set(st, "insert_failed", ainsert_failed); rrddim_set(st, "drop", adrop); rrddim_set(st, "early_drop", aearly_drop); rrdset_done(st); } return 0; }
int registry_init(void) { char filename[FILENAME_MAX + 1]; // registry enabled? if(web_server_mode != WEB_SERVER_MODE_NONE) { registry.enabled = config_get_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0); } else { info("Registry is disabled - use the central netdata"); config_set_boolean(CONFIG_SECTION_REGISTRY, "enabled", 0); registry.enabled = 0; } // pathnames snprintfz(filename, FILENAME_MAX, "%s/registry", netdata_configured_varlib_dir); registry.pathname = config_get(CONFIG_SECTION_REGISTRY, "registry db directory", filename); if(mkdir(registry.pathname, 0770) == -1 && errno != EEXIST) fatal("Cannot create directory '%s'.", registry.pathname); // filenames snprintfz(filename, FILENAME_MAX, "%s/netdata.public.unique.id", registry.pathname); registry.machine_guid_filename = config_get(CONFIG_SECTION_REGISTRY, "netdata unique id file", filename); snprintfz(filename, FILENAME_MAX, "%s/registry.db", registry.pathname); registry.db_filename = config_get(CONFIG_SECTION_REGISTRY, "registry db file", filename); snprintfz(filename, FILENAME_MAX, "%s/registry-log.db", registry.pathname); registry.log_filename = config_get(CONFIG_SECTION_REGISTRY, "registry log file", filename); // configuration options registry.save_registry_every_entries = (unsigned long long)config_get_number(CONFIG_SECTION_REGISTRY, "registry save db every new entries", 1000000); registry.persons_expiration = config_get_number(CONFIG_SECTION_REGISTRY, "registry expire idle persons days", 365) * 86400; registry.registry_domain = config_get(CONFIG_SECTION_REGISTRY, "registry domain", ""); registry.registry_to_announce = config_get(CONFIG_SECTION_REGISTRY, "registry to announce", "https://registry.my-netdata.io"); registry.hostname = config_get(CONFIG_SECTION_REGISTRY, "registry hostname", netdata_configured_hostname); registry.verify_cookies_redirects = config_get_boolean(CONFIG_SECTION_REGISTRY, "verify browser cookies support", 1); setenv("NETDATA_REGISTRY_HOSTNAME", registry.hostname, 1); setenv("NETDATA_REGISTRY_URL", registry.registry_to_announce, 1); registry.max_url_length = (size_t)config_get_number(CONFIG_SECTION_REGISTRY, "max URL length", 1024); if(registry.max_url_length < 10) { registry.max_url_length = 10; config_set_number(CONFIG_SECTION_REGISTRY, "max URL length", (long long)registry.max_url_length); } registry.max_name_length = (size_t)config_get_number(CONFIG_SECTION_REGISTRY, "max URL name length", 50); if(registry.max_name_length < 10) { registry.max_name_length = 10; config_set_number(CONFIG_SECTION_REGISTRY, "max URL name length", (long long)registry.max_name_length); } // initialize entries counters registry.persons_count = 0; registry.machines_count = 0; registry.usages_count = 0; registry.urls_count = 0; registry.persons_urls_count = 0; registry.machines_urls_count = 0; // initialize memory counters registry.persons_memory = 0; registry.machines_memory = 0; registry.urls_memory = 0; registry.persons_urls_memory = 0; registry.machines_urls_memory = 0; // initialize locks netdata_mutex_init(®istry.lock); // create dictionaries registry.persons = dictionary_create(DICTIONARY_FLAGS); registry.machines = dictionary_create(DICTIONARY_FLAGS); avl_init(®istry.registry_urls_root_index, registry_url_compare); // load the registry database if(registry.enabled) { registry_log_open(); registry_db_load(); registry_log_load(); if(unlikely(registry_db_should_be_saved())) registry_db_save(); } return 0; }
static void get_netdata_configured_variables() { backwards_compatible_config(); // ------------------------------------------------------------------------ // get the hostname char buf[HOSTNAME_MAX + 1]; if(gethostname(buf, HOSTNAME_MAX) == -1) error("Cannot get machine hostname."); netdata_configured_hostname = config_get(CONFIG_SECTION_GLOBAL, "hostname", buf); debug(D_OPTIONS, "hostname set to '%s'", netdata_configured_hostname); // ------------------------------------------------------------------------ // get default database size default_rrd_history_entries = (int) config_get_number(CONFIG_SECTION_GLOBAL, "history", align_entries_to_pagesize(default_rrd_memory_mode, RRD_DEFAULT_HISTORY_ENTRIES)); long h = align_entries_to_pagesize(default_rrd_memory_mode, default_rrd_history_entries); if(h != default_rrd_history_entries) { config_set_number(CONFIG_SECTION_GLOBAL, "history", h); default_rrd_history_entries = (int)h; } if(default_rrd_history_entries < 5 || default_rrd_history_entries > RRD_HISTORY_ENTRIES_MAX) { error("Invalid history entries %d given. Defaulting to %d.", default_rrd_history_entries, RRD_DEFAULT_HISTORY_ENTRIES); default_rrd_history_entries = RRD_DEFAULT_HISTORY_ENTRIES; } // ------------------------------------------------------------------------ // get default database update frequency default_rrd_update_every = (int) config_get_number(CONFIG_SECTION_GLOBAL, "update every", UPDATE_EVERY); if(default_rrd_update_every < 1 || default_rrd_update_every > 600) { error("Invalid data collection frequency (update every) %d given. Defaulting to %d.", default_rrd_update_every, UPDATE_EVERY_MAX); default_rrd_update_every = UPDATE_EVERY; } // ------------------------------------------------------------------------ // get system paths netdata_configured_config_dir = config_get(CONFIG_SECTION_GLOBAL, "config directory", CONFIG_DIR); netdata_configured_log_dir = config_get(CONFIG_SECTION_GLOBAL, "log directory", LOG_DIR); netdata_configured_web_dir = config_get(CONFIG_SECTION_GLOBAL, "web files directory", WEB_DIR); netdata_configured_cache_dir = config_get(CONFIG_SECTION_GLOBAL, "cache directory", CACHE_DIR); netdata_configured_varlib_dir = config_get(CONFIG_SECTION_GLOBAL, "lib directory", VARLIB_DIR); netdata_configured_home_dir = config_get(CONFIG_SECTION_GLOBAL, "home directory", CACHE_DIR); { char plugins_dirs[(FILENAME_MAX * 2) + 1]; snprintfz(plugins_dirs, FILENAME_MAX * 2, "\"%s\" \"%s/custom-plugins.d\"", PLUGINS_DIR, CONFIG_DIR); netdata_configured_plugins_dir_base = strdupz(config_get(CONFIG_SECTION_GLOBAL, "plugins directory", plugins_dirs)); quoted_strings_splitter(netdata_configured_plugins_dir_base, plugin_directories, PLUGINSD_MAX_DIRECTORIES, config_isspace); netdata_configured_plugins_dir = plugin_directories[0]; } // ------------------------------------------------------------------------ // get default memory mode for the database default_rrd_memory_mode = rrd_memory_mode_id(config_get(CONFIG_SECTION_GLOBAL, "memory mode", rrd_memory_mode_name(default_rrd_memory_mode))); // ------------------------------------------------------------------------ netdata_configured_host_prefix = config_get(CONFIG_SECTION_GLOBAL, "host access prefix", ""); verify_netdata_host_prefix(); // -------------------------------------------------------------------- // get KSM settings #ifdef MADV_MERGEABLE enable_ksm = config_get_boolean(CONFIG_SECTION_GLOBAL, "memory deduplication (ksm)", enable_ksm); #endif // -------------------------------------------------------------------- // get various system parameters get_system_HZ(); get_system_cpus(); get_system_pid_max(); }
RRDHOST *rrdhost_create(const char *hostname, const char *guid, const char *os, int update_every, long entries, RRD_MEMORY_MODE memory_mode, int health_enabled, int rrdpush_enabled, char *rrdpush_destination, char *rrdpush_api_key, int is_localhost ) { debug(D_RRDHOST, "Host '%s': adding with guid '%s'", hostname, guid); rrd_check_wrlock(); RRDHOST *host = callocz(1, sizeof(RRDHOST)); host->rrd_update_every = (update_every > 0)?update_every:1; host->rrd_history_entries = align_entries_to_pagesize(memory_mode, entries); host->rrd_memory_mode = memory_mode; host->health_enabled = (memory_mode == RRD_MEMORY_MODE_NONE)? 0 : health_enabled; host->rrdpush_enabled = (rrdpush_enabled && rrdpush_destination && *rrdpush_destination && rrdpush_api_key && *rrdpush_api_key); host->rrdpush_destination = (host->rrdpush_enabled)?strdupz(rrdpush_destination):NULL; host->rrdpush_api_key = (host->rrdpush_enabled)?strdupz(rrdpush_api_key):NULL; host->rrdpush_pipe[0] = -1; host->rrdpush_pipe[1] = -1; host->rrdpush_socket = -1; netdata_mutex_init(&host->rrdpush_mutex); netdata_rwlock_init(&host->rrdhost_rwlock); rrdhost_init_hostname(host, hostname); rrdhost_init_machine_guid(host, guid); rrdhost_init_os(host, os); avl_init_lock(&(host->rrdset_root_index), rrdset_compare); avl_init_lock(&(host->rrdset_root_index_name), rrdset_compare_name); avl_init_lock(&(host->rrdfamily_root_index), rrdfamily_compare); avl_init_lock(&(host->variables_root_index), rrdvar_compare); if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete obsolete charts files", 1)) rrdhost_flag_set(host, RRDHOST_DELETE_OBSOLETE_FILES); if(config_get_boolean(CONFIG_SECTION_GLOBAL, "delete orphan hosts files", 1) && !is_localhost) rrdhost_flag_set(host, RRDHOST_DELETE_ORPHAN_FILES); // ------------------------------------------------------------------------ // initialize health variables host->health_log.next_log_id = 1; host->health_log.next_alarm_id = 1; host->health_log.max = 1000; host->health_log.next_log_id = host->health_log.next_alarm_id = (uint32_t)now_realtime_sec(); long n = config_get_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", host->health_log.max); if(n < 10) { error("Host '%s': health configuration has invalid max log entries %ld. Using default %u", host->hostname, n, host->health_log.max); config_set_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", (long)host->health_log.max); } else host->health_log.max = (unsigned int)n; netdata_rwlock_init(&host->health_log.alarm_log_rwlock); char filename[FILENAME_MAX + 1]; if(is_localhost) { host->cache_dir = strdupz(netdata_configured_cache_dir); host->varlib_dir = strdupz(netdata_configured_varlib_dir); } else { // this is not localhost - append our GUID to localhost path snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_cache_dir, host->machine_guid); host->cache_dir = strdupz(filename); if(host->rrd_memory_mode == RRD_MEMORY_MODE_MAP || host->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) { int r = mkdir(host->cache_dir, 0775); if(r != 0 && errno != EEXIST) error("Host '%s': cannot create directory '%s'", host->hostname, host->cache_dir); } snprintfz(filename, FILENAME_MAX, "%s/%s", netdata_configured_varlib_dir, host->machine_guid); host->varlib_dir = strdupz(filename); if(host->health_enabled) { int r = mkdir(host->varlib_dir, 0775); if(r != 0 && errno != EEXIST) error("Host '%s': cannot create directory '%s'", host->hostname, host->varlib_dir); } } if(host->health_enabled) { snprintfz(filename, FILENAME_MAX, "%s/health", host->varlib_dir); int r = mkdir(filename, 0775); if(r != 0 && errno != EEXIST) error("Host '%s': cannot create directory '%s'", host->hostname, filename); } snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir); host->health_log_filename = strdupz(filename); 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"); // ------------------------------------------------------------------------ // load health configuration if(host->health_enabled) { health_alarm_log_load(host); health_alarm_log_open(host); rrdhost_wrlock(host); health_readdir(host, health_config_dir()); rrdhost_unlock(host); } // ------------------------------------------------------------------------ // link it and add it to the index if(is_localhost) { host->next = localhost; localhost = host; } else { if(localhost) { host->next = localhost->next; localhost->next = host; } else localhost = host; } RRDHOST *t = rrdhost_index_add(host); if(t != host) { error("Host '%s': cannot add host with machine guid '%s' to index. It already exists as host '%s' with machine guid '%s'.", host->hostname, host->machine_guid, t->hostname, t->machine_guid); rrdhost_free(host); host = NULL; } else { info("Host '%s' with guid '%s' initialized" ", os %s" ", update every %d" ", memory mode %s" ", history entries %ld" ", streaming %s" " (to '%s' with api key '%s')" ", health %s" ", cache_dir '%s'" ", varlib_dir '%s'" ", health_log '%s'" ", alarms default handler '%s'" ", alarms default recipient '%s'" , host->hostname , host->machine_guid , host->os , host->rrd_update_every , rrd_memory_mode_name(host->rrd_memory_mode) , host->rrd_history_entries , host->rrdpush_enabled?"enabled":"disabled" , host->rrdpush_destination?host->rrdpush_destination:"" , host->rrdpush_api_key?host->rrdpush_api_key:"" , host->health_enabled?"enabled":"disabled" , host->cache_dir , host->varlib_dir , host->health_log_filename , host->health_default_exec , host->health_default_recipient ); } rrd_hosts_available++; return host; }
int do_proc_interrupts(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; static int cpus = -1, do_per_core = -1; 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(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/interrupts"); ff = procfile_open(config_get("plugin:proc:/proc/interrupts", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); } if(unlikely(!ff)) return 1; ff = procfile_readall(ff); if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; uint32_t words = procfile_linewords(ff, 0); if(unlikely(!lines)) { error("Cannot read /proc/interrupts, zero lines reported."); return 1; } // find how many CPUs are there if(unlikely(cpus == -1)) { uint32_t w; cpus = 0; for(w = 0; w < words ; w++) { if(likely(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0)) cpus++; } } if(unlikely(!cpus)) { error("PLUGIN: PROC_INTERRUPTS: Cannot find the number of CPUs in /proc/interrupts"); return 1; } // allocate the size we need; irrs = get_interrupts_array(lines, cpus); irrs[0].used = 0; // loop through all lines for(l = 1; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); irr->used = 0; irr->total = 0; words = procfile_linewords(ff, l); if(unlikely(!words)) continue; irr->id = procfile_lineword(ff, l, 0); if(unlikely(!irr->id || !irr->id[0])) continue; int idlen = strlen(irr->id); if(unlikely(irr->id[idlen - 1] == ':')) irr->id[idlen - 1] = '\0'; int c; for(c = 0; c < cpus ;c++) { if(likely((c + 1) < (int)words)) irr->cpu[c].value = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10); else irr->cpu[c].value = 0; irr->total += irr->cpu[c].value; } if(unlikely(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words)) { strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME); int nlen = strlen(irr->name); int 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); } else { irr->name[MAX_INTERRUPT_NAME - idlen - 1] = '_'; strncpyz(&irr->name[MAX_INTERRUPT_NAME - idlen], irr->id, idlen); } } else { strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME); } irr->used = 1; } RRDSET *st; // -------------------------------------------------------------------- st = rrdset_find_bytype("system", "interrupts"); if(unlikely(!st)) st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED); else rrdset_next(st); 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, irr->id); if(unlikely(!irr->rd)) irr->rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); else rrddim_set_name(st, 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; } } rrddim_set_by_pointer(st, irr->rd, irr->total); } rrdset_done(st); if(likely(do_per_core)) { int c; for(c = 0; c < cpus ;c++) { char id[50+1]; snprintfz(id, 50, "cpu%d_interrupts", c); st = rrdset_find_bytype("cpu", id); if(unlikely(!st)) { char title[100+1]; snprintfz(title, 100, "CPU%d Interrupts", c); st = rrdset_create("cpu", id, NULL, "interrupts", "cpu.interrupts", title, "interrupts/s", 1100 + c, update_every, RRDSET_TYPE_STACKED); } else rrdset_next(st); 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(st, irr->id); if(unlikely(!irr->cpu[c].rd)) irr->cpu[c].rd = rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); else rrddim_set_name(st, irr->cpu[c].rd, irr->name); } rrddim_set_by_pointer(st, irr->cpu[c].rd, irr->cpu[c].value); } rrdset_done(st); } } return 0; }
struct cgroup *cgroup_add(const char *id) { debug(D_CGROUP, "adding cgroup '%s'", id); if(cgroup_root_count >= cgroup_root_max) { info("Maximum number of cgroups reached (%d). Not adding cgroup '%s'", cgroup_root_count, id); return NULL; } int def = cgroup_enable_new_cgroups_detected_at_runtime; const char *chart_id = id; if(!*chart_id) { chart_id = "/"; // disable by default the root cgroup def = 0; debug(D_CGROUP, "cgroup '%s' is the root container (by default %s)", id, (def)?"enabled":"disabled"); } else { if(*chart_id == '/') chart_id++; size_t len = strlen(chart_id); // disable by default the parent cgroup // for known cgroup managers if(!strcmp(chart_id, "lxc") || !strcmp(chart_id, "docker") || !strcmp(chart_id, "libvirt") || !strcmp(chart_id, "qemu") || !strcmp(chart_id, "systemd") || !strcmp(chart_id, "system.slice") || !strcmp(chart_id, "machine.slice") || !strcmp(chart_id, "user") || !strcmp(chart_id, "system") || !strcmp(chart_id, "machine") || // starts with them (len > 6 && !strncmp(chart_id, "user/", 6)) || (len > 11 && !strncmp(chart_id, "user.slice/", 11)) || // ends with them (len > 5 && !strncmp(&chart_id[len - 5], ".user", 5)) || (len > 5 && !strncmp(&chart_id[len - 5], ".swap", 5)) || (len > 6 && !strncmp(&chart_id[len - 6], ".slice", 6)) || (len > 6 && !strncmp(&chart_id[len - 6], ".mount", 6)) || (len > 8 && !strncmp(&chart_id[len - 8], ".session", 8)) || (len > 8 && !strncmp(&chart_id[len - 8], ".service", 8)) || (len > 10 && !strncmp(&chart_id[len - 10], ".partition", 10)) ) { def = 0; debug(D_CGROUP, "cgroup '%s' is %s (by default)", id, (def)?"enabled":"disabled"); } } struct cgroup *cg = calloc(1, sizeof(struct cgroup)); if(!cg) fatal("Cannot allocate memory for cgroup '%s'", id); debug(D_CGROUP, "adding cgroup '%s'", id); cg->id = strdup(id); if(!cg->id) fatal("Cannot allocate memory for cgroup '%s'", id); cg->hash = simple_hash(cg->id); cg->chart_id = strdup(chart_id); if(!cg->chart_id) fatal("Cannot allocate memory for cgroup '%s'", id); cg->chart_title = strdup(chart_id); if(!cg->chart_title) fatal("Cannot allocate memory for cgroup '%s'", id); if(!cgroup_root) cgroup_root = cg; else { // append it struct cgroup *e; for(e = cgroup_root; e->next ;e = e->next) ; e->next = cg; } cgroup_root_count++; // fix the name by calling the external script cgroup_get_chart_id(cg); char option[FILENAME_MAX + 1]; snprintfz(option, FILENAME_MAX, "enable cgroup %s", cg->chart_title); cg->enabled = config_get_boolean("plugin:cgroups", option, def); debug(D_CGROUP, "Added cgroup '%s' with chart id '%s' and title '%s' as %s (default was %s)", cg->id, cg->chart_id, cg->chart_title, (cg->enabled)?"enabled":"disabled", (def)?"enabled":"disabled"); return cg; }
void *proc_main(void *ptr) { (void)ptr; info("PROC Plugin thread created with task id %d", gettid()); if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0) error("Cannot set pthread cancel type to DEFERRED."); if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0) error("Cannot set pthread cancel state to ENABLE."); // disable (by default) various interface that are not needed config_get_boolean("plugin:proc:/proc/net/dev:lo", "enabled", 0); config_get_boolean("plugin:proc:/proc/net/dev:fireqos_monitor", "enabled", 0); // when ZERO, attempt to do it int vdo_proc_net_dev = !config_get_boolean("plugin:proc", "/proc/net/dev", 1); int vdo_proc_diskstats = !config_get_boolean("plugin:proc", "/proc/diskstats", 1); int vdo_proc_net_snmp = !config_get_boolean("plugin:proc", "/proc/net/snmp", 1); int vdo_proc_net_snmp6 = !config_get_boolean("plugin:proc", "/proc/net/snmp6", 1); int vdo_proc_net_netstat = !config_get_boolean("plugin:proc", "/proc/net/netstat", 1); int vdo_proc_net_stat_conntrack = !config_get_boolean("plugin:proc", "/proc/net/stat/conntrack", 1); int vdo_proc_net_ip_vs_stats = !config_get_boolean("plugin:proc", "/proc/net/ip_vs/stats", 1); int vdo_proc_net_stat_synproxy = !config_get_boolean("plugin:proc", "/proc/net/stat/synproxy", 1); int vdo_proc_stat = !config_get_boolean("plugin:proc", "/proc/stat", 1); int vdo_proc_meminfo = !config_get_boolean("plugin:proc", "/proc/meminfo", 1); int vdo_proc_vmstat = !config_get_boolean("plugin:proc", "/proc/vmstat", 1); int vdo_proc_net_rpc_nfs = !config_get_boolean("plugin:proc", "/proc/net/rpc/nfs", 1); int vdo_proc_net_rpc_nfsd = !config_get_boolean("plugin:proc", "/proc/net/rpc/nfsd", 1); int vdo_proc_sys_kernel_random_entropy_avail = !config_get_boolean("plugin:proc", "/proc/sys/kernel/random/entropy_avail", 1); int vdo_proc_interrupts = !config_get_boolean("plugin:proc", "/proc/interrupts", 1); int vdo_proc_softirqs = !config_get_boolean("plugin:proc", "/proc/softirqs", 1); int vdo_proc_net_softnet_stat = !config_get_boolean("plugin:proc", "/proc/net/softnet_stat", 1); int vdo_proc_loadavg = !config_get_boolean("plugin:proc", "/proc/loadavg", 1); int vdo_ipc = !config_get_boolean("plugin:proc", "ipc", 1); int vdo_sys_kernel_mm_ksm = !config_get_boolean("plugin:proc", "/sys/kernel/mm/ksm", 1); int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1); // keep track of the time each module was called unsigned long long sutime_proc_net_dev = 0ULL; unsigned long long sutime_proc_diskstats = 0ULL; unsigned long long sutime_proc_net_snmp = 0ULL; unsigned long long sutime_proc_net_snmp6 = 0ULL; unsigned long long sutime_proc_net_netstat = 0ULL; unsigned long long sutime_proc_net_stat_conntrack = 0ULL; unsigned long long sutime_proc_net_ip_vs_stats = 0ULL; unsigned long long sutime_proc_net_stat_synproxy = 0ULL; unsigned long long sutime_proc_stat = 0ULL; unsigned long long sutime_proc_meminfo = 0ULL; unsigned long long sutime_proc_vmstat = 0ULL; unsigned long long sutime_proc_net_rpc_nfs = 0ULL; unsigned long long sutime_proc_net_rpc_nfsd = 0ULL; unsigned long long sutime_proc_sys_kernel_random_entropy_avail = 0ULL; unsigned long long sutime_proc_interrupts = 0ULL; unsigned long long sutime_proc_softirqs = 0ULL; unsigned long long sutime_proc_net_softnet_stat = 0ULL; unsigned long long sutime_proc_loadavg = 0ULL; unsigned long long sutime_ipc = 0ULL; unsigned long long sutime_sys_kernel_mm_ksm = 0ULL; unsigned long long step = rrd_update_every * 1000000ULL; for(;;) { unsigned long long now = time_usec(); unsigned long long next = now - (now % step) + step; while(now < next) { sleep_usec(next - now); now = time_usec(); } if(unlikely(netdata_exit)) break; // BEGIN -- the job to be done if(!vdo_sys_kernel_mm_ksm) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_sys_kernel_mm_ksm()."); now = time_usec(); vdo_sys_kernel_mm_ksm = do_sys_kernel_mm_ksm(rrd_update_every, (sutime_sys_kernel_mm_ksm > 0)?now - sutime_sys_kernel_mm_ksm:0ULL); sutime_sys_kernel_mm_ksm = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_loadavg) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_loadavg()."); now = time_usec(); vdo_proc_loadavg = do_proc_loadavg(rrd_update_every, (sutime_proc_loadavg > 0)?now - sutime_proc_loadavg:0ULL); sutime_proc_loadavg = now; } if(unlikely(netdata_exit)) break; if(!vdo_ipc) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_ipc()."); now = time_usec(); vdo_ipc = do_ipc(rrd_update_every, (sutime_ipc > 0)?now - sutime_ipc:0ULL); sutime_ipc = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_interrupts) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_interrupts()."); now = time_usec(); vdo_proc_interrupts = do_proc_interrupts(rrd_update_every, (sutime_proc_interrupts > 0)?now - sutime_proc_interrupts:0ULL); sutime_proc_interrupts = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_softirqs) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_softirqs()."); now = time_usec(); vdo_proc_softirqs = do_proc_softirqs(rrd_update_every, (sutime_proc_softirqs > 0)?now - sutime_proc_softirqs:0ULL); sutime_proc_softirqs = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_softnet_stat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_softnet_stat()."); now = time_usec(); vdo_proc_net_softnet_stat = do_proc_net_softnet_stat(rrd_update_every, (sutime_proc_net_softnet_stat > 0)?now - sutime_proc_net_softnet_stat:0ULL); sutime_proc_net_softnet_stat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_sys_kernel_random_entropy_avail) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_sys_kernel_random_entropy_avail()."); now = time_usec(); vdo_proc_sys_kernel_random_entropy_avail = do_proc_sys_kernel_random_entropy_avail(rrd_update_every, (sutime_proc_sys_kernel_random_entropy_avail > 0)?now - sutime_proc_sys_kernel_random_entropy_avail:0ULL); sutime_proc_sys_kernel_random_entropy_avail = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_dev) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_dev()."); now = time_usec(); vdo_proc_net_dev = do_proc_net_dev(rrd_update_every, (sutime_proc_net_dev > 0)?now - sutime_proc_net_dev:0ULL); sutime_proc_net_dev = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_diskstats) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_diskstats()."); now = time_usec(); vdo_proc_diskstats = do_proc_diskstats(rrd_update_every, (sutime_proc_diskstats > 0)?now - sutime_proc_diskstats:0ULL); sutime_proc_diskstats = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_snmp) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp()."); now = time_usec(); vdo_proc_net_snmp = do_proc_net_snmp(rrd_update_every, (sutime_proc_net_snmp > 0)?now - sutime_proc_net_snmp:0ULL); sutime_proc_net_snmp = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_snmp6) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_snmp6()."); now = time_usec(); vdo_proc_net_snmp6 = do_proc_net_snmp6(rrd_update_every, (sutime_proc_net_snmp6 > 0)?now - sutime_proc_net_snmp6:0ULL); sutime_proc_net_snmp6 = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_netstat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_netstat()."); now = time_usec(); vdo_proc_net_netstat = do_proc_net_netstat(rrd_update_every, (sutime_proc_net_netstat > 0)?now - sutime_proc_net_netstat:0ULL); sutime_proc_net_netstat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_stat_conntrack) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_stat_conntrack()."); now = time_usec(); vdo_proc_net_stat_conntrack = do_proc_net_stat_conntrack(rrd_update_every, (sutime_proc_net_stat_conntrack > 0)?now - sutime_proc_net_stat_conntrack:0ULL); sutime_proc_net_stat_conntrack = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_ip_vs_stats) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_ip_vs_stats()."); now = time_usec(); vdo_proc_net_ip_vs_stats = do_proc_net_ip_vs_stats(rrd_update_every, (sutime_proc_net_ip_vs_stats > 0)?now - sutime_proc_net_ip_vs_stats:0ULL); sutime_proc_net_ip_vs_stats = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_stat_synproxy) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_net_stat_synproxy()."); now = time_usec(); vdo_proc_net_stat_synproxy = do_proc_net_stat_synproxy(rrd_update_every, (sutime_proc_net_stat_synproxy > 0)?now - sutime_proc_net_stat_synproxy:0ULL); sutime_proc_net_stat_synproxy = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_stat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_stat()."); now = time_usec(); vdo_proc_stat = do_proc_stat(rrd_update_every, (sutime_proc_stat > 0)?now - sutime_proc_stat:0ULL); sutime_proc_stat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_meminfo) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_meminfo()."); now = time_usec(); vdo_proc_meminfo = do_proc_meminfo(rrd_update_every, (sutime_proc_meminfo > 0)?now - sutime_proc_meminfo:0ULL); sutime_proc_meminfo = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_vmstat) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling vdo_proc_vmstat()."); now = time_usec(); vdo_proc_vmstat = do_proc_vmstat(rrd_update_every, (sutime_proc_vmstat > 0)?now - sutime_proc_vmstat:0ULL); sutime_proc_vmstat = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_rpc_nfsd) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfsd()."); now = time_usec(); vdo_proc_net_rpc_nfsd = do_proc_net_rpc_nfsd(rrd_update_every, (sutime_proc_net_rpc_nfsd > 0)?now - sutime_proc_net_rpc_nfsd:0ULL); sutime_proc_net_rpc_nfsd = now; } if(unlikely(netdata_exit)) break; if(!vdo_proc_net_rpc_nfs) { debug(D_PROCNETDEV_LOOP, "PROCNETDEV: calling do_proc_net_rpc_nfs()."); now = time_usec(); vdo_proc_net_rpc_nfs = do_proc_net_rpc_nfs(rrd_update_every, (sutime_proc_net_rpc_nfs > 0)?now - sutime_proc_net_rpc_nfs:0ULL); sutime_proc_net_rpc_nfs = now; } if(unlikely(netdata_exit)) break; // END -- the job is done // -------------------------------------------------------------------- if(!vdo_cpu_netdata) { global_statistics_charts(); registry_statistics(); } } info("PROC thread exiting"); pthread_exit(NULL); return NULL; }
int do_proc_interrupts(int update_every, unsigned long long dt) { static procfile *ff = NULL; static int cpus = -1, do_per_core = -1; struct interrupt *irrs = NULL; if(dt) {}; if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/interrupts", "interrupts per core", 1); if(!ff) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/interrupts"); ff = procfile_open(config_get("plugin:proc:/proc/interrupts", "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 uint32_t lines = procfile_lines(ff), l; uint32_t words = procfile_linewords(ff, 0), w; if(!lines) { error("Cannot read /proc/interrupts, zero lines reported."); return 1; } // find how many CPUs are there if(cpus == -1) { cpus = 0; for(w = 0; w < words ; w++) { if(strncmp(procfile_lineword(ff, 0, w), "CPU", 3) == 0) cpus++; } } if(!cpus) { error("PLUGIN: PROC_INTERRUPTS: Cannot find the number of CPUs in /proc/interrupts"); return 1; } // allocate the size we need; irrs = get_interrupts_array(lines, cpus); irrs[0].used = 0; // loop through all lines for(l = 1; l < lines ; l++) { struct interrupt *irr = irrindex(irrs, l, cpus); irr->used = 0; irr->total = 0; words = procfile_linewords(ff, l); if(!words) continue; irr->id = procfile_lineword(ff, l, 0); if(!irr->id || !irr->id[0]) continue; int idlen = strlen(irr->id); if(irr->id[idlen - 1] == ':') irr->id[idlen - 1] = '\0'; int c; for(c = 0; c < cpus ; c++) { if((c + 1) < (int)words) irr->value[c] = strtoull(procfile_lineword(ff, l, (uint32_t)(c + 1)), NULL, 10); else irr->value[c] = 0; irr->total += irr->value[c]; } if(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words) { strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME); int nlen = strlen(irr->name); if(nlen < (MAX_INTERRUPT_NAME-1)) { irr->name[nlen] = '_'; strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen); } } else { strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME); } irr->used = 1; } RRDSET *st; // -------------------------------------------------------------------- st = rrdset_find_bytype("system", "interrupts"); if(!st) { st = rrdset_create("system", "interrupts", NULL, "interrupts", NULL, "System interrupts", "interrupts/s", 1000, update_every, RRDSET_TYPE_STACKED); for(l = 0; l < lines ; l++) { struct interrupt *irr = irrindex(irrs, l, cpus); if(!irr->used) continue; rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); } } else rrdset_next(st); for(l = 0; l < lines ; l++) { struct interrupt *irr = irrindex(irrs, l, cpus); if(!irr->used) continue; rrddim_set(st, irr->id, irr->total); } rrdset_done(st); if(do_per_core) { int c; for(c = 0; c < cpus ; c++) { char id[256+1]; snprintfz(id, 256, "cpu%d_interrupts", c); st = rrdset_find_bytype("cpu", id); if(!st) { char name[256+1], title[256+1]; snprintfz(name, 256, "cpu%d_interrupts", c); snprintfz(title, 256, "CPU%d Interrupts", c); st = rrdset_create("cpu", id, name, "interrupts", "cpu.interrupts", title, "interrupts/s", 2000 + c, update_every, RRDSET_TYPE_STACKED); for(l = 0; l < lines ; l++) { struct interrupt *irr = irrindex(irrs, l, cpus); if(!irr->used) continue; rrddim_add(st, irr->id, irr->name, 1, 1, RRDDIM_INCREMENTAL); } } else rrdset_next(st); for(l = 0; l < lines ; l++) { struct interrupt *irr = irrindex(irrs, l, cpus); if(!irr->used) continue; rrddim_set(st, irr->id, irr->value[c]); } rrdset_done(st); } } return 0; }
int do_proc_meminfo(int update_every, unsigned long long dt) { static procfile *ff = NULL; static int do_ram = -1, do_swap = -1, do_hwcorrupt = -1, do_committed = -1, do_writeback = -1, do_kernel = -1, do_slab = -1; if(do_ram == -1) do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1); if(do_swap == -1) do_swap = config_get_boolean("plugin:proc:/proc/meminfo", "system swap", 1); if(do_hwcorrupt == -1) do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_ONDEMAND_ONDEMAND); if(do_committed == -1) do_committed = config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1); if(do_writeback == -1) do_writeback = config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1); if(do_kernel == -1) do_kernel = config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1); if(do_slab == -1) do_slab = config_get_boolean("plugin:proc:/proc/meminfo", "slab memory", 1); if(dt) {}; if(!ff) { char filename[FILENAME_MAX + 1]; snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/meminfo"); ff = procfile_open(config_get("plugin:proc:/proc/meminfo", "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 uint32_t lines = procfile_lines(ff), l; uint32_t words; int hwcorrupted = 0; unsigned long long MemTotal = 0, MemFree = 0, Buffers = 0, Cached = 0, SwapCached = 0, Active = 0, Inactive = 0, ActiveAnon = 0, InactiveAnon = 0, ActiveFile = 0, InactiveFile = 0, Unevictable = 0, Mlocked = 0, SwapTotal = 0, SwapFree = 0, Dirty = 0, Writeback = 0, AnonPages = 0, Mapped = 0, Shmem = 0, Slab = 0, SReclaimable = 0, SUnreclaim = 0, KernelStack = 0, PageTables = 0, NFS_Unstable = 0, Bounce = 0, WritebackTmp = 0, CommitLimit = 0, Committed_AS = 0, VmallocTotal = 0, VmallocUsed = 0, VmallocChunk = 0, AnonHugePages = 0, HugePages_Total = 0, HugePages_Free = 0, HugePages_Rsvd = 0, HugePages_Surp = 0, Hugepagesize = 0, DirectMap4k = 0, DirectMap2M = 0, HardwareCorrupted = 0; for(l = 0; l < lines ;l++) { words = procfile_linewords(ff, l); if(words < 2) continue; char *name = procfile_lineword(ff, l, 0); unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10); if(!MemTotal && strcmp(name, "MemTotal") == 0) MemTotal = value; else if(!MemFree && strcmp(name, "MemFree") == 0) MemFree = value; else if(!Buffers && strcmp(name, "Buffers") == 0) Buffers = value; else if(!Cached && strcmp(name, "Cached") == 0) Cached = value; else if(!SwapCached && strcmp(name, "SwapCached") == 0) SwapCached = value; else if(!Active && strcmp(name, "Active") == 0) Active = value; else if(!Inactive && strcmp(name, "Inactive") == 0) Inactive = value; else if(!ActiveAnon && strcmp(name, "ActiveAnon") == 0) ActiveAnon = value; else if(!InactiveAnon && strcmp(name, "InactiveAnon") == 0) InactiveAnon = value; else if(!ActiveFile && strcmp(name, "ActiveFile") == 0) ActiveFile = value; else if(!InactiveFile && strcmp(name, "InactiveFile") == 0) InactiveFile = value; else if(!Unevictable && strcmp(name, "Unevictable") == 0) Unevictable = value; else if(!Mlocked && strcmp(name, "Mlocked") == 0) Mlocked = value; else if(!SwapTotal && strcmp(name, "SwapTotal") == 0) SwapTotal = value; else if(!SwapFree && strcmp(name, "SwapFree") == 0) SwapFree = value; else if(!Dirty && strcmp(name, "Dirty") == 0) Dirty = value; else if(!Writeback && strcmp(name, "Writeback") == 0) Writeback = value; else if(!AnonPages && strcmp(name, "AnonPages") == 0) AnonPages = value; else if(!Mapped && strcmp(name, "Mapped") == 0) Mapped = value; else if(!Shmem && strcmp(name, "Shmem") == 0) Shmem = value; else if(!Slab && strcmp(name, "Slab") == 0) Slab = value; else if(!SReclaimable && strcmp(name, "SReclaimable") == 0) SReclaimable = value; else if(!SUnreclaim && strcmp(name, "SUnreclaim") == 0) SUnreclaim = value; else if(!KernelStack && strcmp(name, "KernelStack") == 0) KernelStack = value; else if(!PageTables && strcmp(name, "PageTables") == 0) PageTables = value; else if(!NFS_Unstable && strcmp(name, "NFS_Unstable") == 0) NFS_Unstable = value; else if(!Bounce && strcmp(name, "Bounce") == 0) Bounce = value; else if(!WritebackTmp && strcmp(name, "WritebackTmp") == 0) WritebackTmp = value; else if(!CommitLimit && strcmp(name, "CommitLimit") == 0) CommitLimit = value; else if(!Committed_AS && strcmp(name, "Committed_AS") == 0) Committed_AS = value; else if(!VmallocTotal && strcmp(name, "VmallocTotal") == 0) VmallocTotal = value; else if(!VmallocUsed && strcmp(name, "VmallocUsed") == 0) VmallocUsed = value; else if(!VmallocChunk && strcmp(name, "VmallocChunk") == 0) VmallocChunk = value; else if(!HardwareCorrupted && strcmp(name, "HardwareCorrupted") == 0) { HardwareCorrupted = value; hwcorrupted = 1; } else if(!AnonHugePages && strcmp(name, "AnonHugePages") == 0) AnonHugePages = value; else if(!HugePages_Total && strcmp(name, "HugePages_Total") == 0) HugePages_Total = value; else if(!HugePages_Free && strcmp(name, "HugePages_Free") == 0) HugePages_Free = value; else if(!HugePages_Rsvd && strcmp(name, "HugePages_Rsvd") == 0) HugePages_Rsvd = value; else if(!HugePages_Surp && strcmp(name, "HugePages_Surp") == 0) HugePages_Surp = value; else if(!Hugepagesize && strcmp(name, "Hugepagesize") == 0) Hugepagesize = value; else if(!DirectMap4k && strcmp(name, "DirectMap4k") == 0) DirectMap4k = value; else if(!DirectMap2M && strcmp(name, "DirectMap2M") == 0) DirectMap2M = value; } RRDSET *st; // -------------------------------------------------------------------- // http://stackoverflow.com/questions/3019748/how-to-reliably-measure-available-memory-in-linux unsigned long long MemUsed = MemTotal - MemFree - Cached - Buffers; if(do_ram) { st = rrdset_find("system.ram"); if(!st) { st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED); rrddim_add(st, "buffers", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "cached", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "used", MemUsed); rrddim_set(st, "free", MemFree); rrddim_set(st, "cached", Cached); rrddim_set(st, "buffers", Buffers); rrdset_done(st); } // -------------------------------------------------------------------- unsigned long long SwapUsed = SwapTotal - SwapFree; if(do_swap) { st = rrdset_find("system.swap"); if(!st) { st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED); st->isdetail = 1; rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "used", SwapUsed); rrddim_set(st, "free", SwapFree); rrdset_done(st); } // -------------------------------------------------------------------- if(hwcorrupted && do_hwcorrupt && HardwareCorrupted > 0) { do_hwcorrupt = CONFIG_ONDEMAND_YES; st = rrdset_find("mem.hwcorrupt"); if(!st) { st = rrdset_create("mem", "hwcorrupt", NULL, "errors", NULL, "Hardware Corrupted ECC", "MB", 9000, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "HardwareCorrupted", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "HardwareCorrupted", HardwareCorrupted); rrdset_done(st); } // -------------------------------------------------------------------- if(do_committed) { st = rrdset_find("mem.committed"); if(!st) { st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; rrddim_add(st, "Committed_AS", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "Committed_AS", Committed_AS); rrdset_done(st); } // -------------------------------------------------------------------- if(do_writeback) { st = rrdset_find("mem.writeback"); if(!st) { st = rrdset_create("mem", "writeback", NULL, "kernel", NULL, "Writeback Memory", "MB", 4000, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "Dirty", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "Writeback", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "FuseWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "NfsWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "Bounce", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "Dirty", Dirty); rrddim_set(st, "Writeback", Writeback); rrddim_set(st, "FuseWriteback", WritebackTmp); rrddim_set(st, "NfsWriteback", NFS_Unstable); rrddim_set(st, "Bounce", Bounce); rrdset_done(st); } // -------------------------------------------------------------------- if(do_kernel) { st = rrdset_find("mem.kernel"); if(!st) { st = rrdset_create("mem", "kernel", NULL, "kernel", NULL, "Memory Used by Kernel", "MB", 6000, update_every, RRDSET_TYPE_STACKED); st->isdetail = 1; rrddim_add(st, "Slab", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "KernelStack", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "PageTables", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "VmallocUsed", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "KernelStack", KernelStack); rrddim_set(st, "Slab", Slab); rrddim_set(st, "PageTables", PageTables); rrddim_set(st, "VmallocUsed", VmallocUsed); rrdset_done(st); } // -------------------------------------------------------------------- if(do_slab) { st = rrdset_find("mem.slab"); if(!st) { st = rrdset_create("mem", "slab", NULL, "slab", NULL, "Reclaimable Kernel Memory", "MB", 6500, update_every, RRDSET_TYPE_STACKED); st->isdetail = 1; rrddim_add(st, "reclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "unreclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "reclaimable", SReclaimable); rrddim_set(st, "unreclaimable", SUnreclaim); rrdset_done(st); } return 0; }
int do_proc_net_snmp(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1, do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1, do_udp_packets = -1, do_udp_errors = -1, do_icmp_packets = -1, do_icmpmsg = -1, do_udplite_packets = -1; static uint32_t hash_ip = 0, hash_icmp = 0, hash_tcp = 0, hash_udp = 0, hash_icmpmsg = 0, hash_udplite = 0; //static unsigned long long *ip_Forwarding = NULL; //static unsigned long long *ip_DefaultTTL = NULL; static unsigned long long *ip_InReceives = NULL; static unsigned long long *ip_InHdrErrors = NULL; static unsigned long long *ip_InAddrErrors = NULL; static unsigned long long *ip_ForwDatagrams = NULL; static unsigned long long *ip_InUnknownProtos = NULL; static unsigned long long *ip_InDiscards = NULL; static unsigned long long *ip_InDelivers = NULL; static unsigned long long *ip_OutRequests = NULL; static unsigned long long *ip_OutDiscards = NULL; static unsigned long long *ip_OutNoRoutes = NULL; //static unsigned long long *ip_ReasmTimeout = NULL; static unsigned long long *ip_ReasmReqds = NULL; static unsigned long long *ip_ReasmOKs = NULL; static unsigned long long *ip_ReasmFails = NULL; static unsigned long long *ip_FragOKs = NULL; static unsigned long long *ip_FragFails = NULL; static unsigned long long *ip_FragCreates = NULL; static unsigned long long *icmp_InMsgs = NULL; static unsigned long long *icmp_OutMsgs = NULL; static unsigned long long *icmp_InErrors = NULL; static unsigned long long *icmp_OutErrors = NULL; static unsigned long long *icmp_InCsumErrors = NULL; //static unsigned long long *tcp_RtoAlgorithm = NULL; //static unsigned long long *tcp_RtoMin = NULL; //static unsigned long long *tcp_RtoMax = NULL; //static unsigned long long *tcp_MaxConn = NULL; static unsigned long long *tcp_ActiveOpens = NULL; static unsigned long long *tcp_PassiveOpens = NULL; static unsigned long long *tcp_AttemptFails = NULL; static unsigned long long *tcp_EstabResets = NULL; static unsigned long long *tcp_CurrEstab = NULL; static unsigned long long *tcp_InSegs = NULL; static unsigned long long *tcp_OutSegs = NULL; static unsigned long long *tcp_RetransSegs = NULL; static unsigned long long *tcp_InErrs = NULL; static unsigned long long *tcp_OutRsts = NULL; static unsigned long long *tcp_InCsumErrors = NULL; static unsigned long long *udp_InDatagrams = NULL; static unsigned long long *udp_NoPorts = NULL; static unsigned long long *udp_InErrors = NULL; static unsigned long long *udp_OutDatagrams = NULL; static unsigned long long *udp_RcvbufErrors = NULL; static unsigned long long *udp_SndbufErrors = NULL; static unsigned long long *udp_InCsumErrors = NULL; static unsigned long long *udp_IgnoredMulti = NULL; static unsigned long long *udplite_InDatagrams = NULL; static unsigned long long *udplite_NoPorts = NULL; static unsigned long long *udplite_InErrors = NULL; static unsigned long long *udplite_OutDatagrams = NULL; static unsigned long long *udplite_RcvbufErrors = NULL; static unsigned long long *udplite_SndbufErrors = NULL; static unsigned long long *udplite_InCsumErrors = NULL; static unsigned long long *udplite_IgnoredMulti = NULL; if(unlikely(do_ip_packets == -1)) { 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_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); hash_ip = simple_hash("Ip"); hash_tcp = simple_hash("Tcp"); hash_udp = simple_hash("Udp"); hash_icmp = simple_hash("Icmp"); hash_icmpmsg = simple_hash("IcmpMsg"); hash_udplite = simple_hash("UdpLite"); hash_array(ip_data); hash_array(tcp_data); hash_array(udp_data); hash_array(icmp_data); hash_array(icmpmsg_data); hash_array(udplite_data); //ip_Forwarding = netstat_columns_find(ip_data, "Forwarding"); //ip_DefaultTTL = netstat_columns_find(ip_data, "DefaultTTL"); ip_InReceives = netstat_columns_find(ip_data, "InReceives"); ip_InHdrErrors = netstat_columns_find(ip_data, "InHdrErrors"); ip_InAddrErrors = netstat_columns_find(ip_data, "InAddrErrors"); ip_ForwDatagrams = netstat_columns_find(ip_data, "ForwDatagrams"); ip_InUnknownProtos = netstat_columns_find(ip_data, "InUnknownProtos"); ip_InDiscards = netstat_columns_find(ip_data, "InDiscards"); ip_InDelivers = netstat_columns_find(ip_data, "InDelivers"); ip_OutRequests = netstat_columns_find(ip_data, "OutRequests"); ip_OutDiscards = netstat_columns_find(ip_data, "OutDiscards"); ip_OutNoRoutes = netstat_columns_find(ip_data, "OutNoRoutes"); //ip_ReasmTimeout = netstat_columns_find(ip_data, "ReasmTimeout"); ip_ReasmReqds = netstat_columns_find(ip_data, "ReasmReqds"); ip_ReasmOKs = netstat_columns_find(ip_data, "ReasmOKs"); ip_ReasmFails = netstat_columns_find(ip_data, "ReasmFails"); ip_FragOKs = netstat_columns_find(ip_data, "FragOKs"); ip_FragFails = netstat_columns_find(ip_data, "FragFails"); ip_FragCreates = netstat_columns_find(ip_data, "FragCreates"); icmp_InMsgs = netstat_columns_find(icmp_data, "InMsgs"); icmp_OutMsgs = netstat_columns_find(icmp_data, "OutMsgs"); icmp_InErrors = netstat_columns_find(icmp_data, "InErrors"); icmp_OutErrors = netstat_columns_find(icmp_data, "OutErrors"); icmp_InCsumErrors = netstat_columns_find(icmp_data, "InCsumErrors"); //tcp_RtoAlgorithm = netstat_columns_find(tcp_data, "RtoAlgorithm"); //tcp_RtoMin = netstat_columns_find(tcp_data, "RtoMin"); //tcp_RtoMax = netstat_columns_find(tcp_data, "RtoMax"); //tcp_MaxConn = netstat_columns_find(tcp_data, "MaxConn"); tcp_ActiveOpens = netstat_columns_find(tcp_data, "ActiveOpens"); tcp_PassiveOpens = netstat_columns_find(tcp_data, "PassiveOpens"); tcp_AttemptFails = netstat_columns_find(tcp_data, "AttemptFails"); tcp_EstabResets = netstat_columns_find(tcp_data, "EstabResets"); tcp_CurrEstab = netstat_columns_find(tcp_data, "CurrEstab"); tcp_InSegs = netstat_columns_find(tcp_data, "InSegs"); tcp_OutSegs = netstat_columns_find(tcp_data, "OutSegs"); tcp_RetransSegs = netstat_columns_find(tcp_data, "RetransSegs"); tcp_InErrs = netstat_columns_find(tcp_data, "InErrs"); tcp_OutRsts = netstat_columns_find(tcp_data, "OutRsts"); tcp_InCsumErrors = netstat_columns_find(tcp_data, "InCsumErrors"); udp_InDatagrams = netstat_columns_find(udp_data, "InDatagrams"); udp_NoPorts = netstat_columns_find(udp_data, "NoPorts"); udp_InErrors = netstat_columns_find(udp_data, "InErrors"); udp_OutDatagrams = netstat_columns_find(udp_data, "OutDatagrams"); udp_RcvbufErrors = netstat_columns_find(udp_data, "RcvbufErrors"); udp_SndbufErrors = netstat_columns_find(udp_data, "SndbufErrors"); udp_InCsumErrors = netstat_columns_find(udp_data, "InCsumErrors"); udp_IgnoredMulti = netstat_columns_find(udp_data, "IgnoredMulti"); udplite_InDatagrams = netstat_columns_find(udplite_data, "InDatagrams"); udplite_NoPorts = netstat_columns_find(udplite_data, "NoPorts"); udplite_InErrors = netstat_columns_find(udplite_data, "InErrors"); udplite_OutDatagrams = netstat_columns_find(udplite_data, "OutDatagrams"); udplite_RcvbufErrors = netstat_columns_find(udplite_data, "RcvbufErrors"); udplite_SndbufErrors = netstat_columns_find(udplite_data, "SndbufErrors"); udplite_InCsumErrors = netstat_columns_find(udplite_data, "InCsumErrors"); udplite_IgnoredMulti = netstat_columns_find(udplite_data, "IgnoredMulti"); } if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/snmp"); ff = procfile_open(config_get("plugin:proc:/proc/net/snmp", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return 1; } ff = procfile_readall(ff); if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time size_t lines = procfile_lines(ff), l; size_t words; RRDSET *st; for(l = 0; l < lines ;l++) { char *key = procfile_lineword(ff, l, 0); uint32_t hash = simple_hash(key); if(unlikely(hash == hash_ip && strcmp(key, "Ip") == 0)) { size_t h = l++; if(strcmp(procfile_lineword(ff, l, 0), "Ip") != 0) { error("Cannot read Ip line from /proc/net/snmp."); break; } words = procfile_linewords(ff, l); if(words < 3) { error("Cannot read /proc/net/snmp Ip line. Expected 3+ params, read %zu.", words); continue; } // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html parse_line_pair(ff, ip_data, h, l); // -------------------------------------------------------------------- if(do_ip_packets) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".packets"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "packets", NULL, "packets", NULL, "IPv4 Packets" , "packets/s", 3000, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InReceives", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutRequests", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "ForwDatagrams", "forwarded", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InDelivers", "delivered", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "OutRequests", *ip_OutRequests); rrddim_set(st, "InReceives", *ip_InReceives); rrddim_set(st, "ForwDatagrams", *ip_ForwDatagrams); rrddim_set(st, "InDelivers", *ip_InDelivers); rrdset_done(st); } // -------------------------------------------------------------------- if(do_ip_fragsout) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".fragsout"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "fragsout", NULL, "fragments", NULL , "IPv4 Fragments Sent", "packets/s", 3010, update_every , RRDSET_TYPE_LINE); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "FragOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "FragFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "FragCreates", "created", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "FragOKs", *ip_FragOKs); rrddim_set(st, "FragFails", *ip_FragFails); rrddim_set(st, "FragCreates", *ip_FragCreates); rrdset_done(st); } // -------------------------------------------------------------------- if(do_ip_fragsin) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".fragsin"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "fragsin", NULL, "fragments", NULL , "IPv4 Fragments Reassembly", "packets/s", 3011, update_every , RRDSET_TYPE_LINE); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "ReasmOKs", "ok", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "ReasmFails", "failed", -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "ReasmReqds", "all", 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "ReasmOKs", *ip_ReasmOKs); rrddim_set(st, "ReasmFails", *ip_ReasmFails); rrddim_set(st, "ReasmReqds", *ip_ReasmReqds); rrdset_done(st); } // -------------------------------------------------------------------- if(do_ip_errors) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".errors"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "errors", NULL, "errors", NULL, "IPv4 Errors" , "packets/s", 3002, update_every, RRDSET_TYPE_LINE); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "InDiscards", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutDiscards", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InHdrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutNoRoutes", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InAddrErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InUnknownProtos", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "InDiscards", *ip_InDiscards); rrddim_set(st, "OutDiscards", *ip_OutDiscards); rrddim_set(st, "InHdrErrors", *ip_InHdrErrors); rrddim_set(st, "InAddrErrors", *ip_InAddrErrors); rrddim_set(st, "InUnknownProtos", *ip_InUnknownProtos); rrddim_set(st, "OutNoRoutes", *ip_OutNoRoutes); rrdset_done(st); } } else if(unlikely(hash == hash_icmp && strcmp(key, "Icmp") == 0)) { size_t h = l++; if(strcmp(procfile_lineword(ff, l, 0), "Icmp") != 0) { error("Cannot read Icmp line from /proc/net/snmp."); break; } words = procfile_linewords(ff, l); if(words < 3) { error("Cannot read /proc/net/snmp Icmp line. Expected 3+ params, read %zu.", words); continue; } parse_line_pair(ff, icmp_data, h, l); // -------------------------------------------------------------------- if(do_icmp_packets) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmp"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmp", NULL, "icmp", NULL, "IPv4 ICMP Packets" , "packets/s", 2602, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InMsgs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutMsgs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "InMsgs", *icmp_InMsgs); rrddim_set(st, "OutMsgs", *icmp_OutMsgs); rrdset_done(st); st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmp_errors"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmp_errors", NULL, "icmp", NULL , "IPv4 ICMP Errors", "packets/s", 2603, update_every , RRDSET_TYPE_LINE); rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "InErrors", *icmp_InErrors); rrddim_set(st, "OutErrors", *icmp_OutErrors); rrddim_set(st, "InCsumErrors", *icmp_InCsumErrors); rrdset_done(st); } } else if(unlikely(hash == hash_icmpmsg && strcmp(key, "IcmpMsg") == 0)) { size_t h = l++; if(strcmp(procfile_lineword(ff, l, 0), "IcmpMsg") != 0) { error("Cannot read IcmpMsg line from /proc/net/snmp."); break; } parse_line_pair(ff, icmpmsg_data, h, l); // -------------------------------------------------------------------- if(do_icmpmsg) { int i; st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".icmpmsg"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "icmpmsg", NULL, "icmp", NULL, "IPv4 ICMP Messages" , "packets/s", 2604, update_every, RRDSET_TYPE_LINE); for(i = 0; icmpmsg_data[i].name ;i++) rrddim_add(st, icmpmsg_data[i].name, icmpmsg_data[i].label, icmpmsg_data[i].multiplier, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); for(i = 0; icmpmsg_data[i].name ;i++) rrddim_set(st, icmpmsg_data[i].name, icmpmsg_data[i].value); rrdset_done(st); } } else if(unlikely(hash == hash_tcp && strcmp(key, "Tcp") == 0)) { size_t h = l++; if(strcmp(procfile_lineword(ff, l, 0), "Tcp") != 0) { error("Cannot read Tcp line from /proc/net/snmp."); break; } words = procfile_linewords(ff, l); if(words < 3) { error("Cannot read /proc/net/snmp Tcp line. Expected 3+ params, read %zu.", words); continue; } parse_line_pair(ff, tcp_data, h, l); // -------------------------------------------------------------------- // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html if(do_tcp_sockets) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcpsock"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", NULL, "IPv4 TCP Connections" , "active connections", 2500, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "CurrEstab", "connections", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "CurrEstab", *tcp_CurrEstab); rrdset_done(st); } // -------------------------------------------------------------------- if(do_tcp_packets) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcppackets"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", NULL, "IPv4 TCP Packets" , "packets/s", 2600, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InSegs", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutSegs", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "InSegs", *tcp_InSegs); rrddim_set(st, "OutSegs", *tcp_OutSegs); rrdset_done(st); } // -------------------------------------------------------------------- if(do_tcp_errors) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcperrors"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", NULL, "IPv4 TCP Errors" , "packets/s", 2700, update_every, RRDSET_TYPE_LINE); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "InErrs", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "RetransSegs", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "InErrs", *tcp_InErrs); rrddim_set(st, "InCsumErrors", *tcp_InCsumErrors); rrddim_set(st, "RetransSegs", *tcp_RetransSegs); rrdset_done(st); } // -------------------------------------------------------------------- if(do_tcp_handshake) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".tcphandshake"); if(!st) { st = rrdset_create_localhost( RRD_TYPE_NET_SNMP , "tcphandshake" , NULL , "tcp" , NULL , "IPv4 TCP Handshake Issues" , "events/s" , 2900 , update_every , RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "EstabResets", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutRsts", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "ActiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "PassiveOpens", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "AttemptFails", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "TCPSynRetrans", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "EstabResets", *tcp_EstabResets); rrddim_set(st, "OutRsts", *tcp_OutRsts); rrddim_set(st, "ActiveOpens", *tcp_ActiveOpens); rrddim_set(st, "PassiveOpens", *tcp_PassiveOpens); rrddim_set(st, "AttemptFails", *tcp_AttemptFails); rrddim_set(st, "TCPSynRetrans", tcpext_TCPSynRetrans); rrdset_done(st); } } else if(unlikely(hash == hash_udp && strcmp(key, "Udp") == 0)) { size_t h = l++; if(strcmp(procfile_lineword(ff, l, 0), "Udp") != 0) { error("Cannot read Udp line from /proc/net/snmp."); break; } words = procfile_linewords(ff, l); if(words < 3) { error("Cannot read /proc/net/snmp Udp line. Expected 3+ params, read %zu.", words); continue; } parse_line_pair(ff, udp_data, h, l); // -------------------------------------------------------------------- // see http://net-snmp.sourceforge.net/docs/mibs/udp.html if(do_udp_packets) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udppackets"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", NULL, "IPv4 UDP Packets" , "packets/s", 2601, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "InDatagrams", *udp_InDatagrams); rrddim_set(st, "OutDatagrams", *udp_OutDatagrams); rrdset_done(st); } // -------------------------------------------------------------------- if(do_udp_errors) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udperrors"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", NULL, "IPv4 UDP Errors" , "events/s", 2701, update_every, RRDSET_TYPE_LINE); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "InErrors", *udp_InErrors); rrddim_set(st, "NoPorts", *udp_NoPorts); rrddim_set(st, "RcvbufErrors", *udp_RcvbufErrors); rrddim_set(st, "SndbufErrors", *udp_SndbufErrors); rrddim_set(st, "InCsumErrors", *udp_InCsumErrors); rrddim_set(st, "IgnoredMulti", *udp_IgnoredMulti); rrdset_done(st); } } else if(unlikely(hash == hash_udplite && strcmp(key, "UdpLite") == 0)) { size_t h = l++; if(strcmp(procfile_lineword(ff, l, 0), "UdpLite") != 0) { error("Cannot read UdpLite line from /proc/net/snmp."); break; } words = procfile_linewords(ff, l); if(words < 3) { error("Cannot read /proc/net/snmp UdpLite line. Expected 3+ params, read %zu.", words); continue; } parse_line_pair(ff, udplite_data, h, l); // -------------------------------------------------------------------- if(do_udplite_packets) { st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udplite"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udplite", NULL, "udplite", NULL , "IPv4 UDPLite Packets", "packets/s", 2603, update_every , RRDSET_TYPE_LINE); rrddim_add(st, "InDatagrams", "received", 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "OutDatagrams", "sent", -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "InDatagrams", *udplite_InDatagrams); rrddim_set(st, "OutDatagrams", *udplite_OutDatagrams); rrdset_done(st); st = rrdset_find_localhost(RRD_TYPE_NET_SNMP ".udplite_errors"); if(!st) { st = rrdset_create_localhost(RRD_TYPE_NET_SNMP, "udplite_errors", NULL, "udplite", NULL , "IPv4 UDPLite Errors", "packets/s", 2604, update_every , RRDSET_TYPE_LINE); rrddim_add(st, "RcvbufErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "SndbufErrors", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "NoPorts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "IgnoredMulti", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_add(st, "InCsumErrors", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "NoPorts", *udplite_NoPorts); rrddim_set(st, "InErrors", *udplite_InErrors); rrddim_set(st, "InCsumErrors", *udplite_InCsumErrors); rrddim_set(st, "RcvbufErrors", *udplite_RcvbufErrors); rrddim_set(st, "SndbufErrors", *udplite_SndbufErrors); rrddim_set(st, "IgnoredMulti", *udplite_IgnoredMulti); rrdset_done(st); } } } return 0; }