コード例 #1
0
ファイル: proc_net_netstat.c プロジェクト: rlugojr/netdata
static void parse_line_pair(procfile *ff, ARL_BASE *base, size_t header_line, size_t values_line) {
    size_t hwords = procfile_linewords(ff, header_line);
    size_t vwords = procfile_linewords(ff, values_line);
    size_t w;

    if(unlikely(vwords > hwords)) {
        error("File /proc/net/netstat on header line %zu has %zu words, but on value line %zu has %zu words.", header_line, hwords, values_line, vwords);
        vwords = hwords;
    }

    for(w = 1; w < vwords ;w++) {
        if(unlikely(arl_check(base, procfile_lineword(ff, header_line, w), procfile_lineword(ff, values_line, w))))
            break;
    }
}
コード例 #2
0
ファイル: common.c プロジェクト: tvieira/netdata
long get_system_cpus(void) {
    processors = 1;

    #ifdef __APPLE__
        int32_t tmp_processors;

        if (unlikely(GETSYSCTL_BY_NAME("hw.logicalcpu", tmp_processors))) {
            error("Assuming system has %d processors.", processors);
        } else {
            processors = tmp_processors;
        }

        return processors;
    #elif __FreeBSD__
        int32_t tmp_processors;

        if (unlikely(GETSYSCTL_BY_NAME("hw.ncpu", tmp_processors))) {
            error("Assuming system has %d processors.", processors);
        } else {
            processors = tmp_processors;
        }

        return processors;
    #else

    char filename[FILENAME_MAX + 1];
    snprintfz(filename, FILENAME_MAX, "%s/proc/stat", netdata_configured_host_prefix);

    procfile *ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
    if(!ff) {
        error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
        return processors;
    }

    ff = procfile_readall(ff);
    if(!ff) {
        error("Cannot open file '%s'. Assuming system has %d processors.", filename, processors);
        return processors;
    }

    processors = 0;
    unsigned int i;
    for(i = 0; i < procfile_lines(ff); i++) {
        if(!procfile_linewords(ff, i)) continue;

        if(strncmp(procfile_lineword(ff, i, 0), "cpu", 3) == 0) processors++;
    }
    processors--;
    if(processors < 1) processors = 1;

    procfile_close(ff);

    debug(D_SYSTEM, "System has %d processors.", processors);
    return processors;

    #endif /* __APPLE__, __FreeBSD__ */
}
コード例 #3
0
ファイル: proc_net_snmp.c プロジェクト: dvigne/netdata
static void parse_line_pair(procfile *ff, struct netstat_columns *nc, size_t header_line, size_t values_line) {
    size_t hwords = procfile_linewords(ff, header_line);
    size_t vwords = procfile_linewords(ff, values_line);
    size_t w, i;

    if(unlikely(vwords > hwords)) {
        error("File /proc/net/snmp on header line %zu has %zu words, but on value line %zu has %zu words.", header_line, hwords, values_line, vwords);
        vwords = hwords;
    }

    for(w = 1; w < vwords ;w++) {
        char *key = procfile_lineword(ff, header_line, w);
        uint32_t hash = simple_hash(key);

        for(i = 0 ; nc[i].name ;i++) {
            if(unlikely(hash == nc[i].hash && !strcmp(key, nc[i].name))) {
                nc[i].value = str2ull(procfile_lineword(ff, values_line, w));
                break;
            }
        }
    }
}
コード例 #4
0
ファイル: proc_stat.c プロジェクト: firehol/netdata
static int read_schedstat(char *schedstat_filename, struct per_core_cpuidle_chart **cpuidle_charts_address, size_t *schedstat_cores_found) {
    static size_t cpuidle_charts_len = 0;
    static procfile *ff = NULL;
    struct per_core_cpuidle_chart *cpuidle_charts = *cpuidle_charts_address;
    size_t cores_found = 0;

    if(unlikely(!ff)) {
        ff = procfile_open(schedstat_filename, " \t:", PROCFILE_FLAG_DEFAULT);
        if(unlikely(!ff)) return 1;
    }

    ff = procfile_readall(ff);
    if(unlikely(!ff)) return 1;

    size_t lines = procfile_lines(ff), l;
    size_t words;

    for(l = 0; l < lines ;l++) {
        char *row_key = procfile_lineword(ff, l, 0);

        // 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 < 10)) {
                error("Cannot read /proc/schedstat cpu line. Expected 9 params, read %zu.", words);
                return 1;
            }
            cores_found++;

            size_t core = str2ul(&row_key[3]);
            if(unlikely(core >= cores_found)) {
                error("Core %zu found but no more than %zu cores were expected.", core, cores_found);
                return 1;
            }

            if(unlikely(cpuidle_charts_len < cores_found)) {
                cpuidle_charts = reallocz(cpuidle_charts, sizeof(struct per_core_cpuidle_chart) * cores_found);
                *cpuidle_charts_address = cpuidle_charts;
                memset(cpuidle_charts + cpuidle_charts_len, 0, sizeof(struct per_core_cpuidle_chart) * (cores_found - cpuidle_charts_len));
                cpuidle_charts_len = cores_found;
            }

            cpuidle_charts[core].active_time = str2ull(procfile_lineword(ff, l, 7)) / 1000;
        }
    }

    *schedstat_cores_found = cores_found;
    return 0;
}
コード例 #5
0
void cgroup_read_cpuacct_usage(struct cpuacct_usage *ca) {
	static procfile *ff = NULL;

	ca->updated = 0;
	if(ca->filename) {
		ff = procfile_reopen(ff, ca->filename, NULL, PROCFILE_FLAG_DEFAULT);
		if(!ff) return;

		ff = procfile_readall(ff);
		if(!ff) return;

		if(procfile_lines(ff) < 1) {
			error("File '%s' should have 1+ lines but has %u.", ca->filename, procfile_lines(ff));
			return;
		}

		unsigned long i = procfile_linewords(ff, 0);
		if(i <= 0) return;

		// we may have 1 more CPU reported
		while(i > 0) {
			char *s = procfile_lineword(ff, 0, i - 1);
			if(!*s) i--;
			else break;
		}

		if(i != ca->cpus) {
			free(ca->cpu_percpu);

			ca->cpu_percpu = malloc(sizeof(unsigned long long) * i);
			if(!ca->cpu_percpu)
				fatal("Cannot allocate memory (%zu bytes)", sizeof(unsigned long long) * i);

			ca->cpus = i;
		}

		for(i = 0; i < ca->cpus ;i++) {
			ca->cpu_percpu[i] = strtoull(procfile_lineword(ff, 0, i), NULL, 10);
			// fprintf(stderr, "READ '%s': cpu%d/%d: %llu ('%s')\n", ca->filename, i, ca->cpus, ca->cpu_percpu[i], procfile_lineword(ff, 0, i));
		}

		ca->updated = 1;
	}
}
コード例 #6
0
int do_proc_spl_kstat_zfs_arcstats(int update_every, usec_t dt) {
    (void)dt;

    static procfile *ff = NULL;
    static ARL_BASE *arl_base = NULL;

    arcstats.l2exist = -1;

    if(unlikely(!arl_base)) {
        arl_base = arl_create("arcstats", NULL, 60);

        arl_expect(arl_base, "hits", &arcstats.hits);
        arl_expect(arl_base, "misses", &arcstats.misses);
        arl_expect(arl_base, "demand_data_hits", &arcstats.demand_data_hits);
        arl_expect(arl_base, "demand_data_misses", &arcstats.demand_data_misses);
        arl_expect(arl_base, "demand_metadata_hits", &arcstats.demand_metadata_hits);
        arl_expect(arl_base, "demand_metadata_misses", &arcstats.demand_metadata_misses);
        arl_expect(arl_base, "prefetch_data_hits", &arcstats.prefetch_data_hits);
        arl_expect(arl_base, "prefetch_data_misses", &arcstats.prefetch_data_misses);
        arl_expect(arl_base, "prefetch_metadata_hits", &arcstats.prefetch_metadata_hits);
        arl_expect(arl_base, "prefetch_metadata_misses", &arcstats.prefetch_metadata_misses);
        arl_expect(arl_base, "mru_hits", &arcstats.mru_hits);
        arl_expect(arl_base, "mru_ghost_hits", &arcstats.mru_ghost_hits);
        arl_expect(arl_base, "mfu_hits", &arcstats.mfu_hits);
        arl_expect(arl_base, "mfu_ghost_hits", &arcstats.mfu_ghost_hits);
        arl_expect(arl_base, "deleted", &arcstats.deleted);
        arl_expect(arl_base, "mutex_miss", &arcstats.mutex_miss);
        arl_expect(arl_base, "evict_skip", &arcstats.evict_skip);
        arl_expect(arl_base, "evict_not_enough", &arcstats.evict_not_enough);
        arl_expect(arl_base, "evict_l2_cached", &arcstats.evict_l2_cached);
        arl_expect(arl_base, "evict_l2_eligible", &arcstats.evict_l2_eligible);
        arl_expect(arl_base, "evict_l2_ineligible", &arcstats.evict_l2_ineligible);
        arl_expect(arl_base, "evict_l2_skip", &arcstats.evict_l2_skip);
        arl_expect(arl_base, "hash_elements", &arcstats.hash_elements);
        arl_expect(arl_base, "hash_elements_max", &arcstats.hash_elements_max);
        arl_expect(arl_base, "hash_collisions", &arcstats.hash_collisions);
        arl_expect(arl_base, "hash_chains", &arcstats.hash_chains);
        arl_expect(arl_base, "hash_chain_max", &arcstats.hash_chain_max);
        arl_expect(arl_base, "p", &arcstats.p);
        arl_expect(arl_base, "c", &arcstats.c);
        arl_expect(arl_base, "c_min", &arcstats.c_min);
        arl_expect(arl_base, "c_max", &arcstats.c_max);
        arl_expect(arl_base, "size", &arcstats.size);
        arl_expect(arl_base, "hdr_size", &arcstats.hdr_size);
        arl_expect(arl_base, "data_size", &arcstats.data_size);
        arl_expect(arl_base, "metadata_size", &arcstats.metadata_size);
        arl_expect(arl_base, "other_size", &arcstats.other_size);
        arl_expect(arl_base, "anon_size", &arcstats.anon_size);
        arl_expect(arl_base, "anon_evictable_data", &arcstats.anon_evictable_data);
        arl_expect(arl_base, "anon_evictable_metadata", &arcstats.anon_evictable_metadata);
        arl_expect(arl_base, "mru_size", &arcstats.mru_size);
        arl_expect(arl_base, "mru_evictable_data", &arcstats.mru_evictable_data);
        arl_expect(arl_base, "mru_evictable_metadata", &arcstats.mru_evictable_metadata);
        arl_expect(arl_base, "mru_ghost_size", &arcstats.mru_ghost_size);
        arl_expect(arl_base, "mru_ghost_evictable_data", &arcstats.mru_ghost_evictable_data);
        arl_expect(arl_base, "mru_ghost_evictable_metadata", &arcstats.mru_ghost_evictable_metadata);
        arl_expect(arl_base, "mfu_size", &arcstats.mfu_size);
        arl_expect(arl_base, "mfu_evictable_data", &arcstats.mfu_evictable_data);
        arl_expect(arl_base, "mfu_evictable_metadata", &arcstats.mfu_evictable_metadata);
        arl_expect(arl_base, "mfu_ghost_size", &arcstats.mfu_ghost_size);
        arl_expect(arl_base, "mfu_ghost_evictable_data", &arcstats.mfu_ghost_evictable_data);
        arl_expect(arl_base, "mfu_ghost_evictable_metadata", &arcstats.mfu_ghost_evictable_metadata);
        arl_expect(arl_base, "l2_hits", &arcstats.l2_hits);
        arl_expect(arl_base, "l2_misses", &arcstats.l2_misses);
        arl_expect(arl_base, "l2_feeds", &arcstats.l2_feeds);
        arl_expect(arl_base, "l2_rw_clash", &arcstats.l2_rw_clash);
        arl_expect(arl_base, "l2_read_bytes", &arcstats.l2_read_bytes);
        arl_expect(arl_base, "l2_write_bytes", &arcstats.l2_write_bytes);
        arl_expect(arl_base, "l2_writes_sent", &arcstats.l2_writes_sent);
        arl_expect(arl_base, "l2_writes_done", &arcstats.l2_writes_done);
        arl_expect(arl_base, "l2_writes_error", &arcstats.l2_writes_error);
        arl_expect(arl_base, "l2_writes_lock_retry", &arcstats.l2_writes_lock_retry);
        arl_expect(arl_base, "l2_evict_lock_retry", &arcstats.l2_evict_lock_retry);
        arl_expect(arl_base, "l2_evict_reading", &arcstats.l2_evict_reading);
        arl_expect(arl_base, "l2_evict_l1cached", &arcstats.l2_evict_l1cached);
        arl_expect(arl_base, "l2_free_on_write", &arcstats.l2_free_on_write);
        arl_expect(arl_base, "l2_cdata_free_on_write", &arcstats.l2_cdata_free_on_write);
        arl_expect(arl_base, "l2_abort_lowmem", &arcstats.l2_abort_lowmem);
        arl_expect(arl_base, "l2_cksum_bad", &arcstats.l2_cksum_bad);
        arl_expect(arl_base, "l2_io_error", &arcstats.l2_io_error);
        arl_expect(arl_base, "l2_size", &arcstats.l2_size);
        arl_expect(arl_base, "l2_asize", &arcstats.l2_asize);
        arl_expect(arl_base, "l2_hdr_size", &arcstats.l2_hdr_size);
        arl_expect(arl_base, "l2_compress_successes", &arcstats.l2_compress_successes);
        arl_expect(arl_base, "l2_compress_zeros", &arcstats.l2_compress_zeros);
        arl_expect(arl_base, "l2_compress_failures", &arcstats.l2_compress_failures);
        arl_expect(arl_base, "memory_throttle_count", &arcstats.memory_throttle_count);
        arl_expect(arl_base, "duplicate_buffers", &arcstats.duplicate_buffers);
        arl_expect(arl_base, "duplicate_buffers_size", &arcstats.duplicate_buffers_size);
        arl_expect(arl_base, "duplicate_reads", &arcstats.duplicate_reads);
        arl_expect(arl_base, "memory_direct_count", &arcstats.memory_direct_count);
        arl_expect(arl_base, "memory_indirect_count", &arcstats.memory_indirect_count);
        arl_expect(arl_base, "arc_no_grow", &arcstats.arc_no_grow);
        arl_expect(arl_base, "arc_tempreserve", &arcstats.arc_tempreserve);
        arl_expect(arl_base, "arc_loaned_bytes", &arcstats.arc_loaned_bytes);
        arl_expect(arl_base, "arc_prune", &arcstats.arc_prune);
        arl_expect(arl_base, "arc_meta_used", &arcstats.arc_meta_used);
        arl_expect(arl_base, "arc_meta_limit", &arcstats.arc_meta_limit);
        arl_expect(arl_base, "arc_meta_max", &arcstats.arc_meta_max);
        arl_expect(arl_base, "arc_meta_min", &arcstats.arc_meta_min);
        arl_expect(arl_base, "arc_need_free", &arcstats.arc_need_free);
        arl_expect(arl_base, "arc_sys_free", &arcstats.arc_sys_free);
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, ZFS_PROC_ARCSTATS);
        ff = procfile_open(config_get("plugin:proc:" ZFS_PROC_ARCSTATS, "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 < 3)) {
            if(unlikely(words)) error("Cannot read " ZFS_PROC_ARCSTATS " line %zu. Expected 3 params, read %zu.", l, words);
            continue;
        }

        const char *key   = procfile_lineword(ff, l, 0);
        const char *value = procfile_lineword(ff, l, 2);

        if(unlikely(arcstats.l2exist == -1)) {
            if(key[0] == 'l' && key[1] == '2' && key[2] == '_')
                arcstats.l2exist = 1;
        }

        if(unlikely(arl_check(arl_base, key, value))) break;
    }

    if(unlikely(arcstats.l2exist == -1))
        arcstats.l2exist = 0;

    generate_charts_arcstats("proc", update_every);
    generate_charts_arc_summary("proc", update_every);

    return 0;
}
コード例 #7
0
ファイル: proc_stat.c プロジェクト: acecommerce/netdata
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;
}
コード例 #8
0
ファイル: proc_vmstat.c プロジェクト: dvigne/netdata
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;
}
コード例 #9
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;
}
コード例 #10
0
int do_proc_softirqs(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/softirqs", "interrupts per core", 1);

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/softirqs");
        ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
        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 = procfile_linewords(ff, 0);

    if(unlikely(!lines)) {
        error("Cannot read /proc/softirqs, 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_SOFTIRQS: Cannot find the number of CPUs in /proc/softirqs");
        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 c;
        for(c = 0; c < cpus ;c++) {
            if(likely((c + 1) < (int)words))
                irr->cpu[c].value = str2ull(procfile_lineword(ff, l, (uint32_t)(c + 1)));
            else
                irr->cpu[c].value = 0;

            irr->total += irr->cpu[c].value;
        }

        strncpyz(irr->name, irr->id, MAX_INTERRUPT_NAME);

        irr->used = 1;
    }

    // --------------------------------------------------------------------

    static RRDSET *st_system_softirqs = NULL;
    if(unlikely(!st_system_softirqs))
        st_system_softirqs = rrdset_create_localhost(
                "system"
                , "softirqs"
                , NULL
                , "softirqs"
                , NULL
                , "System softirqs"
                , "softirqs/s"
                , PLUGIN_PROC_NAME
                , PLUGIN_PROC_MODULE_SOFTIRQS_NAME
                , NETDATA_CHART_PRIO_SYSTEM_SOFTIRQS
                , update_every
                , RRDSET_TYPE_STACKED
        );
    else
        rrdset_next(st_system_softirqs);

    for(l = 0; l < lines ;l++) {
        struct interrupt *irr = irrindex(irrs, l, cpus);

        if(unlikely(!irr->used)) continue;

        // some interrupt may have changed without changing the total number of lines
        // if the same number of interrupts have been added and removed between two
        // calls of this function.
        if(unlikely(!irr->rd || strncmp(irr->name, irr->rd->name, MAX_INTERRUPT_NAME) != 0)) {
            irr->rd = rrddim_find(st_system_softirqs, irr->id);

            if(unlikely(!irr->rd))
                irr->rd = rrddim_add(st_system_softirqs, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL);
            else
                rrddim_set_name(st_system_softirqs, irr->rd, irr->name);

            // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop
            if(likely(do_per_core)) {
                int c;
                for (c = 0; c < cpus ;c++) irr->cpu[c].rd = NULL;
            }
        }

        rrddim_set_by_pointer(st_system_softirqs, irr->rd, irr->total);
    }

    rrdset_done(st_system_softirqs);

    // --------------------------------------------------------------------

    if(do_per_core) {
        static RRDSET **core_st = NULL;
        static int old_cpus = 0;

        if(old_cpus < cpus) {
            core_st = reallocz(core_st, sizeof(RRDSET *) * cpus);
            memset(&core_st[old_cpus], 0, sizeof(RRDSET *) * (cpus - old_cpus));
            old_cpus = cpus;
        }

        int c;

        for(c = 0; c < cpus ; c++) {
            if(unlikely(!core_st[c])) {
                // find if everything is just zero
                unsigned long long core_sum = 0;

                for (l = 0; l < lines; l++) {
                    struct interrupt *irr = irrindex(irrs, l, cpus);
                    if (unlikely(!irr->used)) continue;
                    core_sum += irr->cpu[c].value;
                }

                if (unlikely(core_sum == 0)) continue; // try next core

                char id[50 + 1];
                snprintfz(id, 50, "cpu%d_softirqs", c);

                char title[100 + 1];
                snprintfz(title, 100, "CPU%d softirqs", c);

                core_st[c] = rrdset_create_localhost(
                        "cpu"
                        , id
                        , NULL
                        , "softirqs"
                        , "cpu.softirqs"
                        , title
                        , "softirqs/s"
                        , PLUGIN_PROC_NAME
                        , PLUGIN_PROC_MODULE_SOFTIRQS_NAME
                        , NETDATA_CHART_PRIO_SOFTIRQS_PER_CORE + c
                        , update_every
                        , RRDSET_TYPE_STACKED
                );
            }
            else
                rrdset_next(core_st[c]);

            for(l = 0; l < lines ;l++) {
                struct interrupt *irr = irrindex(irrs, l, cpus);

                if(unlikely(!irr->used)) continue;

                if(unlikely(!irr->cpu[c].rd)) {
                    irr->cpu[c].rd = rrddim_find(core_st[c], irr->id);

                    if(unlikely(!irr->cpu[c].rd))
                        irr->cpu[c].rd = rrddim_add(core_st[c], irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL);
                    else
                        rrddim_set_name(core_st[c], irr->cpu[c].rd, irr->name);
                }

                rrddim_set_by_pointer(core_st[c], irr->cpu[c].rd, irr->cpu[c].value);
            }

            rrdset_done(core_st[c]);
        }
    }

    return 0;
}
コード例 #11
0
ファイル: proc_net_netstat.c プロジェクト: rlugojr/netdata
int do_proc_net_netstat(int update_every, usec_t dt) {
    (void)dt;

    static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \
        do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1;
    static uint32_t hash_ipext = 0, hash_tcpext = 0;
    static procfile *ff = NULL;

    static ARL_BASE *arl_tcpext = NULL;
    static ARL_BASE *arl_ipext = NULL;

    // --------------------------------------------------------------------
    // IPv4

    // IPv4 bandwidth
    static unsigned long long ipext_InOctets = 0;
    static unsigned long long ipext_OutOctets = 0;

    // IPv4 input errors
    static unsigned long long ipext_InNoRoutes = 0;
    static unsigned long long ipext_InTruncatedPkts = 0;
    static unsigned long long ipext_InCsumErrors = 0;

    // IPv4 multicast bandwidth
    static unsigned long long ipext_InMcastOctets = 0;
    static unsigned long long ipext_OutMcastOctets = 0;

    // IPv4 multicast packets
    static unsigned long long ipext_InMcastPkts = 0;
    static unsigned long long ipext_OutMcastPkts = 0;

    // IPv4 broadcast bandwidth
    static unsigned long long ipext_InBcastOctets = 0;
    static unsigned long long ipext_OutBcastOctets = 0;

    // IPv4 broadcast packets
    static unsigned long long ipext_InBcastPkts = 0;
    static unsigned long long ipext_OutBcastPkts = 0;

    // IPv4 ECN
    static unsigned long long ipext_InNoECTPkts = 0;
    static unsigned long long ipext_InECT1Pkts = 0;
    static unsigned long long ipext_InECT0Pkts = 0;
    static unsigned long long ipext_InCEPkts = 0;

    // --------------------------------------------------------------------
    // IPv4 TCP

    // IPv4 TCP Reordering
    static unsigned long long tcpext_TCPRenoReorder = 0;
    static unsigned long long tcpext_TCPFACKReorder = 0;
    static unsigned long long tcpext_TCPSACKReorder = 0;
    static unsigned long long tcpext_TCPTSReorder = 0;

    // IPv4 TCP SYN Cookies
    static unsigned long long tcpext_SyncookiesSent = 0;
    static unsigned long long tcpext_SyncookiesRecv = 0;
    static unsigned long long tcpext_SyncookiesFailed = 0;

    // IPv4 TCP Out Of Order Queue
    // http://www.spinics.net/lists/netdev/msg204696.html
    static unsigned long long tcpext_TCPOFOQueue = 0; // Number of packets queued in OFO queue
    static unsigned long long tcpext_TCPOFODrop = 0;  // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
    static unsigned long long tcpext_TCPOFOMerge = 0; // Number of packets in OFO that were merged with other packets.
    static unsigned long long tcpext_OfoPruned = 0;   // packets dropped from out-of-order queue because of socket buffer overrun

    // IPv4 TCP connection resets
    // https://github.com/ecki/net-tools/blob/bd8bceaed2311651710331a7f8990c3e31be9840/statistics.c
    static unsigned long long tcpext_TCPAbortOnData = 0;    // connections reset due to unexpected data
    static unsigned long long tcpext_TCPAbortOnClose = 0;   // connections reset due to early user close
    static unsigned long long tcpext_TCPAbortOnMemory = 0;  // connections aborted due to memory pressure
    static unsigned long long tcpext_TCPAbortOnTimeout = 0; // connections aborted due to timeout
    static unsigned long long tcpext_TCPAbortOnLinger = 0;  // connections aborted after user close in linger timeout
    static unsigned long long tcpext_TCPAbortFailed = 0;    // times unable to send RST due to no memory

    // IPv4 TCP memory pressures
    static unsigned long long tcpext_TCPMemoryPressures = 0;

    if(unlikely(!arl_ipext)) {
        hash_ipext = simple_hash("IpExt");
        hash_tcpext = simple_hash("TcpExt");

        do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_inerrors  = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND);
        do_mcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_bcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_mcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
        do_bcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND);
        do_ecn       = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);

        do_tcpext_reorder    = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_ofo        = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_memory     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_ONDEMAND_ONDEMAND);

        arl_ipext  = arl_create("netstat/ipext", NULL, 60);
        arl_tcpext = arl_create("netstat/tcpext", NULL, 60);

        // --------------------------------------------------------------------
        // IPv4

        if(do_bandwidth != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InOctets",  &ipext_InOctets);
            arl_expect(arl_ipext, "OutOctets", &ipext_OutOctets);
        }

        if(do_inerrors != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InNoRoutes",      &ipext_InNoRoutes);
            arl_expect(arl_ipext, "InTruncatedPkts", &ipext_InTruncatedPkts);
            arl_expect(arl_ipext, "InCsumErrors",    &ipext_InCsumErrors);
        }

        if(do_mcast != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InMcastOctets", &ipext_InMcastOctets);
            arl_expect(arl_ipext, "OutMcastOctets", &ipext_OutMcastOctets);
        }

        if(do_mcast_p != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InMcastPkts",  &ipext_InMcastPkts);
            arl_expect(arl_ipext, "OutMcastPkts", &ipext_OutMcastPkts);
        }

        if(do_bcast != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InBcastPkts",  &ipext_InBcastPkts);
            arl_expect(arl_ipext, "OutBcastPkts", &ipext_OutBcastPkts);
        }

        if(do_bcast_p != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InBcastOctets",  &ipext_InBcastOctets);
            arl_expect(arl_ipext, "OutBcastOctets", &ipext_OutBcastOctets);
        }

        if(do_ecn != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_ipext, "InNoECTPkts", &ipext_InNoECTPkts);
            arl_expect(arl_ipext, "InECT1Pkts",  &ipext_InECT1Pkts);
            arl_expect(arl_ipext, "InECT0Pkts",  &ipext_InECT0Pkts);
            arl_expect(arl_ipext, "InCEPkts",    &ipext_InCEPkts);
        }

        // --------------------------------------------------------------------
        // IPv4 TCP

        if(do_tcpext_reorder != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "TCPFACKReorder", &tcpext_TCPFACKReorder);
            arl_expect(arl_tcpext, "TCPSACKReorder", &tcpext_TCPSACKReorder);
            arl_expect(arl_tcpext, "TCPRenoReorder", &tcpext_TCPRenoReorder);
            arl_expect(arl_tcpext, "TCPTSReorder",   &tcpext_TCPTSReorder);
        }

        if(do_tcpext_syscookies != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "SyncookiesSent",   &tcpext_SyncookiesSent);
            arl_expect(arl_tcpext, "SyncookiesRecv",   &tcpext_SyncookiesRecv);
            arl_expect(arl_tcpext, "SyncookiesFailed", &tcpext_SyncookiesFailed);
        }

        if(do_tcpext_ofo != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "TCPOFOQueue", &tcpext_TCPOFOQueue);
            arl_expect(arl_tcpext, "TCPOFODrop",  &tcpext_TCPOFODrop);
            arl_expect(arl_tcpext, "TCPOFOMerge", &tcpext_TCPOFOMerge);
            arl_expect(arl_tcpext, "OfoPruned",   &tcpext_OfoPruned);
        }

        if(do_tcpext_connaborts != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "TCPAbortOnData",    &tcpext_TCPAbortOnData);
            arl_expect(arl_tcpext, "TCPAbortOnClose",   &tcpext_TCPAbortOnClose);
            arl_expect(arl_tcpext, "TCPAbortOnMemory",  &tcpext_TCPAbortOnMemory);
            arl_expect(arl_tcpext, "TCPAbortOnTimeout", &tcpext_TCPAbortOnTimeout);
            arl_expect(arl_tcpext, "TCPAbortOnLinger",  &tcpext_TCPAbortOnLinger);
            arl_expect(arl_tcpext, "TCPAbortFailed",    &tcpext_TCPAbortFailed);
        }

        if(do_tcpext_memory != CONFIG_ONDEMAND_NO) {
            arl_expect(arl_tcpext, "TCPMemoryPressures", &tcpext_TCPMemoryPressures);
        }
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/netstat");
        ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
        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;

    arl_begin(arl_ipext);
    arl_begin(arl_tcpext);

    for(l = 0; l < lines ;l++) {
        char *key = procfile_lineword(ff, l, 0);
        uint32_t hash = simple_hash(key);

        if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) {
            size_t h = l++;

            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %zu.", words);
                continue;
            }

            parse_line_pair(ff, arl_ipext, h, l);

            RRDSET *st;

            // --------------------------------------------------------------------

            if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (ipext_InOctets || ipext_OutOctets))) {
                do_bandwidth = CONFIG_ONDEMAND_YES;
                st = rrdset_find("system.ipv4");
                if(unlikely(!st)) {
                    st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);

                    rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InOctets", ipext_InOctets);
                rrddim_set(st, "OutOctets", ipext_OutOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (ipext_InNoRoutes || ipext_InTruncatedPkts))) {
                do_inerrors = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.inerrors");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InNoRoutes", "noroutes", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InTruncatedPkts", "truncated", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InCsumErrors", "checksum", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InNoRoutes", ipext_InNoRoutes);
                rrddim_set(st, "InTruncatedPkts", ipext_InTruncatedPkts);
                rrddim_set(st, "InCsumErrors", ipext_InCsumErrors);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (ipext_InMcastOctets || ipext_OutMcastOctets))) {
                do_mcast = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.mcast");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
                    st->isdetail = 1;

                    rrddim_add(st, "InMcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutMcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InMcastOctets", ipext_InMcastOctets);
                rrddim_set(st, "OutMcastOctets", ipext_OutMcastOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (ipext_InBcastOctets || ipext_OutBcastOctets))) {
                do_bcast = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.bcast");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
                    st->isdetail = 1;

                    rrddim_add(st, "InBcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutBcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InBcastOctets", ipext_InBcastOctets);
                rrddim_set(st, "OutBcastOctets", ipext_OutBcastOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (ipext_InMcastPkts || ipext_OutMcastPkts))) {
                do_mcast_p = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.mcastpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 8600, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InMcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InMcastPkts", ipext_InMcastPkts);
                rrddim_set(st, "OutMcastPkts", ipext_OutMcastPkts);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (ipext_InBcastPkts || ipext_OutBcastPkts))) {
                do_bcast_p = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.bcastpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InBcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutBcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InBcastPkts", ipext_InBcastPkts);
                rrddim_set(st, "OutBcastPkts", ipext_OutBcastPkts);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (ipext_InCEPkts || ipext_InECT0Pkts || ipext_InECT1Pkts || ipext_InNoECTPkts))) {
                do_ecn = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.ecnpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InCEPkts", ipext_InCEPkts);
                rrddim_set(st, "InNoECTPkts", ipext_InNoECTPkts);
                rrddim_set(st, "InECT0Pkts", ipext_InECT0Pkts);
                rrddim_set(st, "InECT1Pkts", ipext_InECT1Pkts);
                rrdset_done(st);
            }
        }
        else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) {
            size_t h = l++;

            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %zu.", words);
                continue;
            }

            parse_line_pair(ff, arl_tcpext, h, l);

            RRDSET *st;

            // --------------------------------------------------------------------

            if(do_tcpext_memory == CONFIG_ONDEMAND_YES || (do_tcpext_memory == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPMemoryPressures))) {
                do_tcpext_memory = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpmemorypressures");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpmemorypressures", NULL, "tcp", NULL, "TCP Memory Pressures", "events/s", 3000, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPMemoryPressures",   "pressures",  1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPMemoryPressures", tcpext_TCPMemoryPressures);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPAbortOnData || tcpext_TCPAbortOnClose || tcpext_TCPAbortOnMemory || tcpext_TCPAbortOnTimeout || tcpext_TCPAbortOnLinger || tcpext_TCPAbortFailed))) {
                do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpconnaborts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnLinger",  "linger",      1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortFailed",    "failed",     -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPAbortOnData",    tcpext_TCPAbortOnData);
                rrddim_set(st, "TCPAbortOnClose",   tcpext_TCPAbortOnClose);
                rrddim_set(st, "TCPAbortOnMemory",  tcpext_TCPAbortOnMemory);
                rrddim_set(st, "TCPAbortOnTimeout", tcpext_TCPAbortOnTimeout);
                rrddim_set(st, "TCPAbortOnLinger",  tcpext_TCPAbortOnLinger);
                rrddim_set(st, "TCPAbortFailed",    tcpext_TCPAbortFailed);
                rrdset_done(st);
            }
            // --------------------------------------------------------------------

            if(do_tcpext_reorder == CONFIG_ONDEMAND_YES || (do_tcpext_reorder == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPRenoReorder || tcpext_TCPFACKReorder || tcpext_TCPSACKReorder || tcpext_TCPTSReorder))) {
                do_tcpext_reorder = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpreorders");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpreorders", NULL, "tcp", NULL, "TCP Reordered Packets by Detection Method", "packets/s", 3020, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPTSReorder",   "timestamp",   1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPSACKReorder", "sack",        1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPFACKReorder", "fack",        1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPRenoReorder", "reno",        1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPTSReorder",   tcpext_TCPTSReorder);
                rrddim_set(st, "TCPSACKReorder", tcpext_TCPSACKReorder);
                rrddim_set(st, "TCPFACKReorder", tcpext_TCPFACKReorder);
                rrddim_set(st, "TCPRenoReorder", tcpext_TCPRenoReorder);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && (tcpext_TCPOFOQueue || tcpext_TCPOFODrop || tcpext_TCPOFOMerge))) {
                do_tcpext_ofo = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpofo");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPOFODrop",  "dropped", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPOFOMerge", "merged",   1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OfoPruned",   "pruned",  -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPOFOQueue",   tcpext_TCPOFOQueue);
                rrddim_set(st, "TCPOFODrop",    tcpext_TCPOFODrop);
                rrddim_set(st, "TCPOFOMerge",   tcpext_TCPOFOMerge);
                rrddim_set(st, "OfoPruned",     tcpext_OfoPruned);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (tcpext_SyncookiesSent || tcpext_SyncookiesRecv || tcpext_SyncookiesFailed))) {
                do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpsyncookies");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "SyncookiesRecv",   tcpext_SyncookiesRecv);
                rrddim_set(st, "SyncookiesSent",   tcpext_SyncookiesSent);
                rrddim_set(st, "SyncookiesFailed", tcpext_SyncookiesFailed);
                rrdset_done(st);
            }

        }
    }

    return 0;
}
コード例 #12
0
ファイル: proc_softirqs.c プロジェクト: SanskritFritz/netdata
int do_proc_softirqs(int update_every, unsigned long long dt) {
	static procfile *ff = NULL;
	static int cpus = -1, do_per_core = -1;

	if(dt) {};

	if(do_per_core == -1) do_per_core = config_get_boolean("plugin:proc:/proc/softirqs", "interrupts per core", 1);

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/softirqs");
		ff = procfile_open(config_get("plugin:proc:/proc/softirqs", "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;

	// 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 > MAX_INTERRUPT_CPUS) cpus = MAX_INTERRUPT_CPUS;
	}

	if(!cpus) {
		error("PLUGIN: PROC_SOFTIRQS: Cannot find the number of CPUs in /proc/softirqs");
		return 1;
	}

	// allocate the size we need;
	struct interrupt irrs[lines];
	irrs[0].used = 0;

	// loop through all lines
	for(l = 1; l < lines ;l++) {
		struct interrupt *irr = &irrs[l];
		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];
		}

		strncpy(irr->name, irr->id, MAX_INTERRUPT_NAME);
		irr->name[MAX_INTERRUPT_NAME] = '\0';

		irr->used = 1;
	}

	RRDSET *st;

	// --------------------------------------------------------------------

	st = rrdset_find_bytype("system", "softirqs");
	if(!st) {
		st = rrdset_create("system", "softirqs", NULL, "system", "System softirqs", "softirqs/s", 1001, update_every, RRDSET_TYPE_STACKED);

		for(l = 0; l < lines ;l++) {
			if(!irrs[l].used) continue;
			rrddim_add(st, irrs[l].id, irrs[l].name, 1, 1, RRDDIM_INCREMENTAL);
		}
	}
	else rrdset_next(st);

	for(l = 0; l < lines ;l++) {
		if(!irrs[l].used) continue;
		rrddim_set(st, irrs[l].id, irrs[l].total);
	}
	rrdset_done(st);

	if(do_per_core) {
		int c;

		for(c = 0; c < cpus ; c++) {
			char family[256];
			snprintf(family, 256, "cpu%d", c);

			char id[256];
			snprintf(id, 256, "cpu%d_softirqs", c);

			st = rrdset_find_bytype("cpu", id);
			if(!st) {
				// find if everything is zero
				unsigned long long core_sum = 0 ;
				for(l = 0; l < lines ;l++) {
					if(!irrs[l].used) continue;
					core_sum += irrs[l].value[c];
				}
				if(core_sum == 0) continue; // try next core

				char name[256], title[256];
				snprintf(name, 256, "cpu%d_softirqs", c);
				snprintf(title, 256, "CPU%d softirqs", c);
				st = rrdset_create("cpu", id, name, family, title, "softirqs/s", 3000 + c, update_every, RRDSET_TYPE_STACKED);

				for(l = 0; l < lines ;l++) {
					if(!irrs[l].used) continue;
					rrddim_add(st, irrs[l].id, irrs[l].name, 1, 1, RRDDIM_INCREMENTAL);
				}
			}
			else rrdset_next(st);

			for(l = 0; l < lines ;l++) {
				if(!irrs[l].used) continue;
				rrddim_set(st, irrs[l].id, irrs[l].value[c]);
			}
			rrdset_done(st);
		}
	}

	return 0;
}
コード例 #13
0
ファイル: proc_diskstats.c プロジェクト: Alexniver/netdata
int do_proc_diskstats(int update_every, unsigned long long dt) {
	static procfile *ff = NULL;
	static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
	static int enable_new_disks = -1;
	static int do_io = -1, do_ops = -1, do_mops = -1, do_iotime = -1, do_qops = -1, do_util = -1, do_backlog = -1;

	if(enable_new_disks == -1)	enable_new_disks = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", CONFIG_ONDEMAND_ONDEMAND);

	if(do_io == -1)		do_io 		= config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "bandwidth for all disks", CONFIG_ONDEMAND_ONDEMAND);
	if(do_ops == -1)	do_ops 		= config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "operations for all disks", CONFIG_ONDEMAND_ONDEMAND);
	if(do_mops == -1)	do_mops 	= config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "merged operations for all disks", CONFIG_ONDEMAND_ONDEMAND);
	if(do_iotime == -1)	do_iotime 	= config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "i/o time for all disks", CONFIG_ONDEMAND_ONDEMAND);
	if(do_qops == -1)	do_qops 	= config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "queued operations for all disks", CONFIG_ONDEMAND_ONDEMAND);
	if(do_util == -1)	do_util 	= config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "utilization percentage for all disks", CONFIG_ONDEMAND_ONDEMAND);
	if(do_backlog == -1)do_backlog 	= config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "backlog for all disks", CONFIG_ONDEMAND_ONDEMAND);

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/diskstats");
		ff = procfile_open(config_get("plugin:proc:/proc/diskstats", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
	}
	if(!ff) return 1;

	if(!path_to_get_hw_sector_size[0]) {
		char filename[FILENAME_MAX + 1];
		snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/block/%s/queue/hw_sector_size");
		snprintf(path_to_get_hw_sector_size, FILENAME_MAX, "%s%s", global_host_prefix, config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", filename));
	}

	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;

	for(l = 0; l < lines ;l++) {
		char *disk;
		unsigned long long 	major = 0, minor = 0,
							reads = 0,  mreads = 0,  readsectors = 0,  readms = 0,
							writes = 0, mwrites = 0, writesectors = 0, writems = 0,
							queued_ios = 0, busy_ms = 0, backlog_ms = 0;

		unsigned long long 	last_reads = 0,  last_readsectors = 0,  last_readms = 0,
							last_writes = 0, last_writesectors = 0, last_writems = 0,
							last_busy_ms = 0;

		words = procfile_linewords(ff, l);
		if(words < 14) continue;

		major 			= strtoull(procfile_lineword(ff, l, 0), NULL, 10);
		minor 			= strtoull(procfile_lineword(ff, l, 1), NULL, 10);
		disk 			= procfile_lineword(ff, l, 2);

		// # of reads completed # of writes completed
		// This is the total number of reads or writes completed successfully.
		reads 			= strtoull(procfile_lineword(ff, l, 3), NULL, 10); 	// rd_ios
		writes 			= strtoull(procfile_lineword(ff, l, 7), NULL, 10); 	// wr_ios

		// # of reads merged # of writes merged
		// Reads and writes which are adjacent to each other may be merged for
	    // efficiency.  Thus two 4K reads may become one 8K read before it is
	    // ultimately handed to the disk, and so it will be counted (and queued)
		mreads		 	= strtoull(procfile_lineword(ff, l, 4), NULL, 10); 	// rd_merges_or_rd_sec
		mwrites 		= strtoull(procfile_lineword(ff, l, 8), NULL, 10); 	// wr_merges

		// # of sectors read # of sectors written
		// This is the total number of sectors read or written successfully.
		readsectors 	= strtoull(procfile_lineword(ff, l, 5), NULL, 10); 	// rd_sec_or_wr_ios
		writesectors 	= strtoull(procfile_lineword(ff, l, 9), NULL, 10); 	// wr_sec

		// # of milliseconds spent reading # of milliseconds spent writing
		// This is the total number of milliseconds spent by all reads or writes (as
		// measured from __make_request() to end_that_request_last()).
		readms 			= strtoull(procfile_lineword(ff, l, 6), NULL, 10); 	// rd_ticks_or_wr_sec
		writems 		= strtoull(procfile_lineword(ff, l, 10), NULL, 10);	// wr_ticks

		// # of I/Os currently in progress
		// The only field that should go to zero. Incremented as requests are
		// given to appropriate struct request_queue and decremented as they finish.
		queued_ios 		= strtoull(procfile_lineword(ff, l, 11), NULL, 10);	// ios_pgr

		// # of milliseconds spent doing I/Os
		// This field increases so long as field queued_ios is nonzero.
		busy_ms 		= strtoull(procfile_lineword(ff, l, 12), NULL, 10);	// tot_ticks

		// weighted # of milliseconds spent doing I/Os
		// This field is incremented at each I/O start, I/O completion, I/O
		// merge, or read of these stats by the number of I/Os in progress
		// (field queued_ios) times the number of milliseconds spent doing I/O since the
		// last update of this field.  This can provide an easy measure of both
		// I/O completion time and the backlog that may be accumulating.
		backlog_ms 		= strtoull(procfile_lineword(ff, l, 13), NULL, 10);	// rq_ticks


		int def_enabled = 0;

		// remove slashes from disk names
		char *s;
		for(s = disk; *s ;s++) if(*s == '/') *s = '_';

		switch(major) {
			case 9: // MDs
			case 43: // network block
			case 144: // nfs
			case 145: // nfs
			case 146: // nfs
			case 199: // veritas
			case 201: // veritas
			case 251: // dm
				def_enabled = enable_new_disks;
				break;

			case 48: // RAID
			case 49: // RAID
			case 50: // RAID
			case 51: // RAID
			case 52: // RAID
			case 53: // RAID
			case 54: // RAID
			case 55: // RAID
			case 112: // RAID
			case 136: // RAID
			case 137: // RAID
			case 138: // RAID
			case 139: // RAID
			case 140: // RAID
			case 141: // RAID
			case 142: // RAID
			case 143: // RAID
			case 179: // MMC
			case 180: // USB
				if(minor % 8) def_enabled = 0; // partitions
				else def_enabled = enable_new_disks;
				break;

			case 8: // scsi disks
			case 65: // scsi disks
			case 66: // scsi disks
			case 67: // scsi disks
			case 68: // scsi disks
			case 69: // scsi disks
			case 70: // scsi disks
			case 71: // scsi disks
			case 72: // scsi disks
			case 73: // scsi disks
			case 74: // scsi disks
			case 75: // scsi disks
			case 76: // scsi disks
			case 77: // scsi disks
			case 78: // scsi disks
			case 79: // scsi disks
			case 80: // i2o
			case 81: // i2o
			case 82: // i2o
			case 83: // i2o
			case 84: // i2o
			case 85: // i2o
			case 86: // i2o
			case 87: // i2o
			case 101: // hyperdisk
			case 102: // compressed
			case 104: // scsi
			case 105: // scsi
			case 106: // scsi
			case 107: // scsi
			case 108: // scsi
			case 109: // scsi
			case 110: // scsi
			case 111: // scsi
			case 114: // bios raid
			case 116: // ram board
			case 128: // scsi
			case 129: // scsi
			case 130: // scsi
			case 131: // scsi
			case 132: // scsi
			case 133: // scsi
			case 134: // scsi
			case 135: // scsi
			case 153: // raid
			case 202: // xen
			case 253: // virtio
			case 256: // flash
			case 257: // flash
			case 259: // nvme0n1 issue #119
				if(minor % 16) def_enabled = 0; // partitions
				else def_enabled = enable_new_disks;
				break;

			case 160: // raid
			case 161: // raid
				if(minor % 32) def_enabled = 0; // partitions
				else def_enabled = enable_new_disks;
				break;

			case 3: // ide
			case 13: // 8bit ide
			case 22: // ide
			case 33: // ide
			case 34: // ide
			case 56: // ide
			case 57: // ide
			case 88: // ide
			case 89: // ide
			case 90: // ide
			case 91: // ide
				if(minor % 64) def_enabled = 0; // partitions
				else def_enabled = enable_new_disks;
				break;

			case 252: // zram
				def_enabled = 0;
				break;

			default:
				def_enabled = 0;
				break;
		}

		int ddo_io = do_io, ddo_ops = do_ops, ddo_mops = do_mops, ddo_iotime = do_iotime, ddo_qops = do_qops, ddo_util = do_util, ddo_backlog = do_backlog;

		// check which charts are enabled for this disk
		{
			char var_name[4096 + 1];
			snprintf(var_name, 4096, "plugin:proc:/proc/diskstats:%s", disk);
			def_enabled = config_get_boolean_ondemand(var_name, "enabled", def_enabled);
			if(def_enabled == CONFIG_ONDEMAND_NO) continue;
			if(def_enabled == CONFIG_ONDEMAND_ONDEMAND && !reads && !writes) continue;


			ddo_io 		= config_get_boolean_ondemand(var_name, "bandwidth", ddo_io);
			ddo_ops 	= config_get_boolean_ondemand(var_name, "operations", ddo_ops);
			ddo_mops 	= config_get_boolean_ondemand(var_name, "merged operations", ddo_mops);
			ddo_iotime 	= config_get_boolean_ondemand(var_name, "i/o time", ddo_iotime);
			ddo_qops 	= config_get_boolean_ondemand(var_name, "queued operations", ddo_qops);
			ddo_util 	= config_get_boolean_ondemand(var_name, "utilization percentage", ddo_util);
			ddo_backlog = config_get_boolean_ondemand(var_name, "backlog", ddo_backlog);

			// by default, do not add charts that do not have values
			if(ddo_io == CONFIG_ONDEMAND_ONDEMAND && !reads && !writes) ddo_io = 0;
			if(ddo_mops == CONFIG_ONDEMAND_ONDEMAND && mreads == 0 && mwrites == 0) ddo_mops = 0;
			if(ddo_iotime == CONFIG_ONDEMAND_ONDEMAND && readms == 0 && writems == 0) ddo_iotime = 0;
			if(ddo_util == CONFIG_ONDEMAND_ONDEMAND && busy_ms == 0) ddo_util = 0;
			if(ddo_backlog == CONFIG_ONDEMAND_ONDEMAND && backlog_ms == 0) ddo_backlog = 0;
			if(ddo_qops == CONFIG_ONDEMAND_ONDEMAND && backlog_ms == 0) ddo_qops = 0;

			// for absolute values, we need to switch the setting to 'yes'
			// to allow it refresh from now on
			if(ddo_qops == CONFIG_ONDEMAND_ONDEMAND) config_set(var_name, "queued operations", "yes");
		}

		RRDSET *st;

		// --------------------------------------------------------------------

		int sector_size = 512;
		if(ddo_io) {
			st = rrdset_find_bytype(RRD_TYPE_DISK, disk);
			if(!st) {
				char tf[FILENAME_MAX + 1], *t;
				char ssfilename[FILENAME_MAX + 1];

				strncpy(tf, disk, FILENAME_MAX);
				tf[FILENAME_MAX] = '\0';

				// replace all / with !
				while((t = strchr(tf, '/'))) *t = '!';

				snprintf(ssfilename, FILENAME_MAX, path_to_get_hw_sector_size, tf);
				FILE *fpss = fopen(ssfilename, "r");
				if(fpss) {
					char ssbuffer[1025];
					char *tmp = fgets(ssbuffer, 1024, fpss);

					if(tmp) {
						sector_size = atoi(tmp);
						if(sector_size <= 0) {
							error("Invalid sector size %d for device %s in %s. Assuming 512.", sector_size, disk, ssfilename);
							sector_size = 512;
						}
					}
					else error("Cannot read data for sector size for device %s from %s. Assuming 512.", disk, ssfilename);

					fclose(fpss);
				}
				else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);

				st = rrdset_create(RRD_TYPE_DISK, disk, NULL, disk, "disk.io", "Disk I/O Bandwidth", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);

				rrddim_add(st, "reads", NULL, sector_size, 1024, RRDDIM_INCREMENTAL);
				rrddim_add(st, "writes", NULL, sector_size * -1, 1024, RRDDIM_INCREMENTAL);
			}
			else rrdset_next_usec(st, dt);

			last_readsectors  = rrddim_set(st, "reads", readsectors);
			last_writesectors = rrddim_set(st, "writes", writesectors);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------

		if(ddo_ops) {
			st = rrdset_find_bytype("disk_ops", disk);
			if(!st) {
				st = rrdset_create("disk_ops", disk, NULL, disk, "disk.ops", "Disk Completed I/O Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
				st->isdetail = 1;

				rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
				rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
			}
			else rrdset_next_usec(st, dt);

			last_reads  = rrddim_set(st, "reads", reads);
			last_writes = rrddim_set(st, "writes", writes);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------

		if(ddo_qops) {
			st = rrdset_find_bytype("disk_qops", disk);
			if(!st) {
				st = rrdset_create("disk_qops", disk, NULL, disk, "disk.qops", "Disk Current I/O Operations", "operations", 2002, update_every, RRDSET_TYPE_LINE);
				st->isdetail = 1;

				rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
			}
			else rrdset_next_usec(st, dt);

			rrddim_set(st, "operations", queued_ios);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------

		if(ddo_backlog) {
			st = rrdset_find_bytype("disk_backlog", disk);
			if(!st) {
				st = rrdset_create("disk_backlog", disk, NULL, disk, "disk.backlog", "Disk Backlog", "backlog (ms)", 2003, update_every, RRDSET_TYPE_AREA);
				st->isdetail = 1;

				rrddim_add(st, "backlog", NULL, 1, 10, RRDDIM_INCREMENTAL);
			}
			else rrdset_next_usec(st, dt);

			rrddim_set(st, "backlog", backlog_ms);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------

		if(ddo_util) {
			st = rrdset_find_bytype("disk_util", disk);
			if(!st) {
				st = rrdset_create("disk_util", disk, NULL, disk, "disk.util", "Disk Utilization Time", "% of time working", 2004, update_every, RRDSET_TYPE_AREA);
				st->isdetail = 1;

				rrddim_add(st, "utilization", NULL, 1, 10, RRDDIM_INCREMENTAL);
			}
			else rrdset_next_usec(st, dt);

			last_busy_ms = rrddim_set(st, "utilization", busy_ms);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------

		if(ddo_mops) {
			st = rrdset_find_bytype("disk_mops", disk);
			if(!st) {
				st = rrdset_create("disk_mops", disk, NULL, disk, "disk.mops", "Disk Merged Operations", "merged operations/s", 2021, update_every, RRDSET_TYPE_LINE);
				st->isdetail = 1;

				rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
				rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
			}
			else rrdset_next_usec(st, dt);

			rrddim_set(st, "reads", mreads);
			rrddim_set(st, "writes", mwrites);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------

		if(ddo_iotime) {
			st = rrdset_find_bytype("disk_iotime", disk);
			if(!st) {
				st = rrdset_create("disk_iotime", disk, NULL, disk, "disk.iotime", "Disk Total I/O Time", "milliseconds/s", 2022, update_every, RRDSET_TYPE_LINE);
				st->isdetail = 1;

				rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_INCREMENTAL);
				rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_INCREMENTAL);
			}
			else rrdset_next_usec(st, dt);

			last_readms  = rrddim_set(st, "reads", readms);
			last_writems = rrddim_set(st, "writes", writems);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------
		// calculate differential charts
		// only if this is not the first time we run

		if(dt) {
			if(ddo_iotime && ddo_ops) {
				st = rrdset_find_bytype("disk_await", disk);
				if(!st) {
					st = rrdset_create("disk_await", disk, NULL, disk, "disk.await", "Average Completed I/O Operation Time", "ms per operation", 2005, update_every, RRDSET_TYPE_LINE);
					st->isdetail = 1;

					rrddim_add(st, "reads", NULL, 1, 1, RRDDIM_ABSOLUTE);
					rrddim_add(st, "writes", NULL, -1, 1, RRDDIM_ABSOLUTE);
				}
				else rrdset_next_usec(st, dt);

				rrddim_set(st, "reads", (reads - last_reads) ? (readms - last_readms) / (reads - last_reads) : 0);
				rrddim_set(st, "writes", (writes - last_writes) ? (writems - last_writems) / (writes - last_writes) : 0);
				rrdset_done(st);
			}

			if(ddo_io && ddo_ops) {
				st = rrdset_find_bytype("disk_avgsz", disk);
				if(!st) {
					st = rrdset_create("disk_avgsz", disk, NULL, disk, "disk.avgsz", "Average Completed I/O Operation Bandwidth", "kilobytes per operation", 2006, update_every, RRDSET_TYPE_AREA);
					st->isdetail = 1;

					rrddim_add(st, "reads", NULL, sector_size, 1024, RRDDIM_ABSOLUTE);
					rrddim_add(st, "writes", NULL, -sector_size, 1024, RRDDIM_ABSOLUTE);
				}
				else rrdset_next_usec(st, dt);

				rrddim_set(st, "reads", (reads - last_reads) ? (readsectors - last_readsectors) / (reads - last_reads) : 0);
				rrddim_set(st, "writes", (writes - last_writes) ? (writesectors - last_writesectors) / (writes - last_writes) : 0);
				rrdset_done(st);
			}

			if(ddo_util && ddo_ops) {
				st = rrdset_find_bytype("disk_svctm", disk);
				if(!st) {
					st = rrdset_create("disk_svctm", disk, NULL, disk, "disk.svctm", "Average Service Time", "ms per operation", 2007, update_every, RRDSET_TYPE_LINE);
					st->isdetail = 1;

					rrddim_add(st, "svctm", NULL, 1, 1, RRDDIM_ABSOLUTE);
				}
				else rrdset_next_usec(st, dt);

				rrddim_set(st, "svctm", ((reads - last_reads) + (writes - last_writes)) ? (busy_ms - last_busy_ms) / ((reads - last_reads) + (writes - last_writes)) : 0);
				rrdset_done(st);
			}
		}
	}

	return 0;
}
コード例 #14
0
ファイル: proc_net_netstat.c プロジェクト: cppmx/netdata
int do_proc_net_netstat(int update_every, usec_t dt) {
    (void)dt;

    static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \
        do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1,
        do_tcpext_listen = -1;

    static uint32_t hash_ipext = 0, hash_tcpext = 0;
    static procfile *ff = NULL;

    static ARL_BASE *arl_tcpext = NULL;
    static ARL_BASE *arl_ipext = NULL;

    // --------------------------------------------------------------------
    // IPv4

    // IPv4 bandwidth
    static unsigned long long ipext_InOctets = 0;
    static unsigned long long ipext_OutOctets = 0;

    // IPv4 input errors
    static unsigned long long ipext_InNoRoutes = 0;
    static unsigned long long ipext_InTruncatedPkts = 0;
    static unsigned long long ipext_InCsumErrors = 0;

    // IPv4 multicast bandwidth
    static unsigned long long ipext_InMcastOctets = 0;
    static unsigned long long ipext_OutMcastOctets = 0;

    // IPv4 multicast packets
    static unsigned long long ipext_InMcastPkts = 0;
    static unsigned long long ipext_OutMcastPkts = 0;

    // IPv4 broadcast bandwidth
    static unsigned long long ipext_InBcastOctets = 0;
    static unsigned long long ipext_OutBcastOctets = 0;

    // IPv4 broadcast packets
    static unsigned long long ipext_InBcastPkts = 0;
    static unsigned long long ipext_OutBcastPkts = 0;

    // IPv4 ECN
    static unsigned long long ipext_InNoECTPkts = 0;
    static unsigned long long ipext_InECT1Pkts = 0;
    static unsigned long long ipext_InECT0Pkts = 0;
    static unsigned long long ipext_InCEPkts = 0;

    // --------------------------------------------------------------------
    // IPv4 TCP

    // IPv4 TCP Reordering
    static unsigned long long tcpext_TCPRenoReorder = 0;
    static unsigned long long tcpext_TCPFACKReorder = 0;
    static unsigned long long tcpext_TCPSACKReorder = 0;
    static unsigned long long tcpext_TCPTSReorder = 0;

    // IPv4 TCP SYN Cookies
    static unsigned long long tcpext_SyncookiesSent = 0;
    static unsigned long long tcpext_SyncookiesRecv = 0;
    static unsigned long long tcpext_SyncookiesFailed = 0;

    // IPv4 TCP Out Of Order Queue
    // http://www.spinics.net/lists/netdev/msg204696.html
    static unsigned long long tcpext_TCPOFOQueue = 0; // Number of packets queued in OFO queue
    static unsigned long long tcpext_TCPOFODrop = 0;  // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
    static unsigned long long tcpext_TCPOFOMerge = 0; // Number of packets in OFO that were merged with other packets.
    static unsigned long long tcpext_OfoPruned = 0;   // packets dropped from out-of-order queue because of socket buffer overrun

    // IPv4 TCP connection resets
    // https://github.com/ecki/net-tools/blob/bd8bceaed2311651710331a7f8990c3e31be9840/statistics.c
    static unsigned long long tcpext_TCPAbortOnData = 0;    // connections reset due to unexpected data
    static unsigned long long tcpext_TCPAbortOnClose = 0;   // connections reset due to early user close
    static unsigned long long tcpext_TCPAbortOnMemory = 0;  // connections aborted due to memory pressure
    static unsigned long long tcpext_TCPAbortOnTimeout = 0; // connections aborted due to timeout
    static unsigned long long tcpext_TCPAbortOnLinger = 0;  // connections aborted after user close in linger timeout
    static unsigned long long tcpext_TCPAbortFailed = 0;    // times unable to send RST due to no memory

    // https://perfchron.com/2015/12/26/investigating-linux-network-issues-with-netstat-and-nstat/
    static unsigned long long tcpext_ListenOverflows = 0;   // times the listen queue of a socket overflowed
    static unsigned long long tcpext_ListenDrops = 0;       // SYNs to LISTEN sockets ignored

    // IPv4 TCP memory pressures
    static unsigned long long tcpext_TCPMemoryPressures = 0;

    // shared: tcpext_TCPSynRetrans


    if(unlikely(!arl_ipext)) {
        hash_ipext = simple_hash("IpExt");
        hash_tcpext = simple_hash("TcpExt");

        do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_BOOLEAN_AUTO);
        do_inerrors  = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_BOOLEAN_AUTO);
        do_mcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_BOOLEAN_AUTO);
        do_bcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_BOOLEAN_AUTO);
        do_mcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_BOOLEAN_AUTO);
        do_bcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_BOOLEAN_AUTO);
        do_ecn       = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_BOOLEAN_AUTO);

        do_tcpext_reorder    = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_BOOLEAN_AUTO);
        do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_BOOLEAN_AUTO);
        do_tcpext_ofo        = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_BOOLEAN_AUTO);
        do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_BOOLEAN_AUTO);
        do_tcpext_memory     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_BOOLEAN_AUTO);
        do_tcpext_listen     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP listen issues", CONFIG_BOOLEAN_AUTO);

        arl_ipext  = arl_create("netstat/ipext", NULL, 60);
        arl_tcpext = arl_create("netstat/tcpext", NULL, 60);

        // --------------------------------------------------------------------
        // IPv4

        if(do_bandwidth != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_ipext, "InOctets",  &ipext_InOctets);
            arl_expect(arl_ipext, "OutOctets", &ipext_OutOctets);
        }

        if(do_inerrors != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_ipext, "InNoRoutes",      &ipext_InNoRoutes);
            arl_expect(arl_ipext, "InTruncatedPkts", &ipext_InTruncatedPkts);
            arl_expect(arl_ipext, "InCsumErrors",    &ipext_InCsumErrors);
        }

        if(do_mcast != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_ipext, "InMcastOctets", &ipext_InMcastOctets);
            arl_expect(arl_ipext, "OutMcastOctets", &ipext_OutMcastOctets);
        }

        if(do_mcast_p != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_ipext, "InMcastPkts",  &ipext_InMcastPkts);
            arl_expect(arl_ipext, "OutMcastPkts", &ipext_OutMcastPkts);
        }

        if(do_bcast != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_ipext, "InBcastPkts",  &ipext_InBcastPkts);
            arl_expect(arl_ipext, "OutBcastPkts", &ipext_OutBcastPkts);
        }

        if(do_bcast_p != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_ipext, "InBcastOctets",  &ipext_InBcastOctets);
            arl_expect(arl_ipext, "OutBcastOctets", &ipext_OutBcastOctets);
        }

        if(do_ecn != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_ipext, "InNoECTPkts", &ipext_InNoECTPkts);
            arl_expect(arl_ipext, "InECT1Pkts",  &ipext_InECT1Pkts);
            arl_expect(arl_ipext, "InECT0Pkts",  &ipext_InECT0Pkts);
            arl_expect(arl_ipext, "InCEPkts",    &ipext_InCEPkts);
        }

        // --------------------------------------------------------------------
        // IPv4 TCP

        if(do_tcpext_reorder != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_tcpext, "TCPFACKReorder", &tcpext_TCPFACKReorder);
            arl_expect(arl_tcpext, "TCPSACKReorder", &tcpext_TCPSACKReorder);
            arl_expect(arl_tcpext, "TCPRenoReorder", &tcpext_TCPRenoReorder);
            arl_expect(arl_tcpext, "TCPTSReorder",   &tcpext_TCPTSReorder);
        }

        if(do_tcpext_syscookies != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_tcpext, "SyncookiesSent",   &tcpext_SyncookiesSent);
            arl_expect(arl_tcpext, "SyncookiesRecv",   &tcpext_SyncookiesRecv);
            arl_expect(arl_tcpext, "SyncookiesFailed", &tcpext_SyncookiesFailed);
        }

        if(do_tcpext_ofo != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_tcpext, "TCPOFOQueue", &tcpext_TCPOFOQueue);
            arl_expect(arl_tcpext, "TCPOFODrop",  &tcpext_TCPOFODrop);
            arl_expect(arl_tcpext, "TCPOFOMerge", &tcpext_TCPOFOMerge);
            arl_expect(arl_tcpext, "OfoPruned",   &tcpext_OfoPruned);
        }

        if(do_tcpext_connaborts != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_tcpext, "TCPAbortOnData",    &tcpext_TCPAbortOnData);
            arl_expect(arl_tcpext, "TCPAbortOnClose",   &tcpext_TCPAbortOnClose);
            arl_expect(arl_tcpext, "TCPAbortOnMemory",  &tcpext_TCPAbortOnMemory);
            arl_expect(arl_tcpext, "TCPAbortOnTimeout", &tcpext_TCPAbortOnTimeout);
            arl_expect(arl_tcpext, "TCPAbortOnLinger",  &tcpext_TCPAbortOnLinger);
            arl_expect(arl_tcpext, "TCPAbortFailed",    &tcpext_TCPAbortFailed);
        }

        if(do_tcpext_memory != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_tcpext, "TCPMemoryPressures", &tcpext_TCPMemoryPressures);
        }

        if(do_tcpext_listen != CONFIG_BOOLEAN_NO) {
            arl_expect(arl_tcpext, "ListenOverflows", &tcpext_ListenOverflows);
            arl_expect(arl_tcpext, "ListenDrops",     &tcpext_ListenDrops);
        }

        // shared metrics
        arl_expect(arl_tcpext, "TCPSynRetrans", &tcpext_TCPSynRetrans);
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/netstat");
        ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
        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;

    arl_begin(arl_ipext);
    arl_begin(arl_tcpext);

    for(l = 0; l < lines ;l++) {
        char *key = procfile_lineword(ff, l, 0);
        uint32_t hash = simple_hash(key);

        if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) {
            size_t h = l++;

            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %zu.", words);
                continue;
            }

            parse_line_pair(ff, arl_ipext, h, l);

            // --------------------------------------------------------------------

            if(do_bandwidth == CONFIG_BOOLEAN_YES || (do_bandwidth == CONFIG_BOOLEAN_AUTO && (ipext_InOctets || ipext_OutOctets))) {
                do_bandwidth = CONFIG_BOOLEAN_YES;
                static RRDSET *st_system_ipv4 = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_system_ipv4)) {
                    st_system_ipv4 = rrdset_create_localhost(
                            "system"
                            , "ipv4"
                            , NULL
                            , "network"
                            , NULL
                            , "IPv4 Bandwidth"
                            , "kilobits/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_SYSTEM_IPV4
                            , update_every
                            , RRDSET_TYPE_AREA
                    );

                    rd_in  = rrddim_add(st_system_ipv4, "InOctets",  "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_system_ipv4, "OutOctets", "sent",    -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_system_ipv4);

                rrddim_set_by_pointer(st_system_ipv4, rd_in,  ipext_InOctets);
                rrddim_set_by_pointer(st_system_ipv4, rd_out, ipext_OutOctets);

                rrdset_done(st_system_ipv4);
            }

            // --------------------------------------------------------------------

            if(do_inerrors == CONFIG_BOOLEAN_YES || (do_inerrors == CONFIG_BOOLEAN_AUTO && (ipext_InNoRoutes || ipext_InTruncatedPkts))) {
                do_inerrors = CONFIG_BOOLEAN_YES;
                static RRDSET *st_ipv4_inerrors = NULL;
                static RRDDIM *rd_noroutes = NULL, *rd_truncated = NULL, *rd_checksum = NULL;

                if(unlikely(!st_ipv4_inerrors)) {
                    st_ipv4_inerrors = rrdset_create_localhost(
                            "ipv4"
                            , "inerrors"
                            , NULL
                            , "errors"
                            , NULL
                            , "IPv4 Input Errors"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_ERRORS
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_ipv4_inerrors, RRDSET_FLAG_DETAIL);

                    rd_noroutes  = rrddim_add(st_ipv4_inerrors, "InNoRoutes",      "noroutes",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_truncated = rrddim_add(st_ipv4_inerrors, "InTruncatedPkts", "truncated", 1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_checksum  = rrddim_add(st_ipv4_inerrors, "InCsumErrors",    "checksum",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_inerrors);

                rrddim_set_by_pointer(st_ipv4_inerrors, rd_noroutes,  ipext_InNoRoutes);
                rrddim_set_by_pointer(st_ipv4_inerrors, rd_truncated, ipext_InTruncatedPkts);
                rrddim_set_by_pointer(st_ipv4_inerrors, rd_checksum,  ipext_InCsumErrors);

                rrdset_done(st_ipv4_inerrors);
            }

            // --------------------------------------------------------------------

            if(do_mcast == CONFIG_BOOLEAN_YES || (do_mcast == CONFIG_BOOLEAN_AUTO && (ipext_InMcastOctets || ipext_OutMcastOctets))) {
                do_mcast = CONFIG_BOOLEAN_YES;
                static RRDSET *st_ipv4_mcast = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_ipv4_mcast)) {
                    st_ipv4_mcast = rrdset_create_localhost(
                            "ipv4"
                            , "mcast"
                            , NULL
                            , "multicast"
                            , NULL
                            , "IPv4 Multicast Bandwidth"
                            , "kilobits/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_MCAST
                            , update_every
                            , RRDSET_TYPE_AREA
                    );

                    rrdset_flag_set(st_ipv4_mcast, RRDSET_FLAG_DETAIL);

                    rd_in  = rrddim_add(st_ipv4_mcast, "InMcastOctets",  "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_ipv4_mcast, "OutMcastOctets", "sent",    -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_mcast);

                rrddim_set_by_pointer(st_ipv4_mcast, rd_in,  ipext_InMcastOctets);
                rrddim_set_by_pointer(st_ipv4_mcast, rd_out, ipext_OutMcastOctets);

                rrdset_done(st_ipv4_mcast);
            }

            // --------------------------------------------------------------------

            if(do_bcast == CONFIG_BOOLEAN_YES || (do_bcast == CONFIG_BOOLEAN_AUTO && (ipext_InBcastOctets || ipext_OutBcastOctets))) {
                do_bcast = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ipv4_bcast = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_ipv4_bcast)) {
                    st_ipv4_bcast = rrdset_create_localhost(
                            "ipv4"
                            , "bcast"
                            , NULL
                            , "broadcast"
                            , NULL
                            , "IPv4 Broadcast Bandwidth"
                            , "kilobits/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_BCAST
                            , update_every
                            , RRDSET_TYPE_AREA
                    );

                    rrdset_flag_set(st_ipv4_bcast, RRDSET_FLAG_DETAIL);

                    rd_in  = rrddim_add(st_ipv4_bcast, "InBcastOctets",  "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_ipv4_bcast, "OutBcastOctets", "sent",    -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_bcast);

                rrddim_set_by_pointer(st_ipv4_bcast, rd_in,  ipext_InBcastOctets);
                rrddim_set_by_pointer(st_ipv4_bcast, rd_out, ipext_OutBcastOctets);

                rrdset_done(st_ipv4_bcast);
            }

            // --------------------------------------------------------------------

            if(do_mcast_p == CONFIG_BOOLEAN_YES || (do_mcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InMcastPkts || ipext_OutMcastPkts))) {
                do_mcast_p = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ipv4_mcastpkts = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_ipv4_mcastpkts)) {
                    st_ipv4_mcastpkts = rrdset_create_localhost(
                            "ipv4"
                            , "mcastpkts"
                            , NULL
                            , "multicast"
                            , NULL
                            , "IPv4 Multicast Packets"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_MCAST + 10
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_ipv4_mcastpkts, RRDSET_FLAG_DETAIL);

                    rd_in  = rrddim_add(st_ipv4_mcastpkts, "InMcastPkts",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_ipv4_mcastpkts, "OutMcastPkts", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else rrdset_next(st_ipv4_mcastpkts);

                rrddim_set_by_pointer(st_ipv4_mcastpkts, rd_in,  ipext_InMcastPkts);
                rrddim_set_by_pointer(st_ipv4_mcastpkts, rd_out, ipext_OutMcastPkts);

                rrdset_done(st_ipv4_mcastpkts);
            }

            // --------------------------------------------------------------------

            if(do_bcast_p == CONFIG_BOOLEAN_YES || (do_bcast_p == CONFIG_BOOLEAN_AUTO && (ipext_InBcastPkts || ipext_OutBcastPkts))) {
                do_bcast_p = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ipv4_bcastpkts = NULL;
                static RRDDIM *rd_in = NULL, *rd_out = NULL;

                if(unlikely(!st_ipv4_bcastpkts)) {
                    st_ipv4_bcastpkts = rrdset_create_localhost(
                            "ipv4"
                            , "bcastpkts"
                            , NULL
                            , "broadcast"
                            , NULL
                            , "IPv4 Broadcast Packets"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_BCAST + 10
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_ipv4_bcastpkts, RRDSET_FLAG_DETAIL);

                    rd_in  = rrddim_add(st_ipv4_bcastpkts, "InBcastPkts",  "received", 1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_out = rrddim_add(st_ipv4_bcastpkts, "OutBcastPkts", "sent",    -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_bcastpkts);

                rrddim_set_by_pointer(st_ipv4_bcastpkts, rd_in,  ipext_InBcastPkts);
                rrddim_set_by_pointer(st_ipv4_bcastpkts, rd_out, ipext_OutBcastPkts);

                rrdset_done(st_ipv4_bcastpkts);
            }

            // --------------------------------------------------------------------

            if(do_ecn == CONFIG_BOOLEAN_YES || (do_ecn == CONFIG_BOOLEAN_AUTO && (ipext_InCEPkts || ipext_InECT0Pkts || ipext_InECT1Pkts || ipext_InNoECTPkts))) {
                do_ecn = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ecnpkts = NULL;
                static RRDDIM *rd_cep = NULL, *rd_noectp = NULL, *rd_ectp0 = NULL, *rd_ectp1 = NULL;

                if(unlikely(!st_ecnpkts)) {
                    st_ecnpkts = rrdset_create_localhost(
                            "ipv4"
                            , "ecnpkts"
                            , NULL
                            , "ecn"
                            , NULL
                            , "IPv4 ECN Statistics"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_ECN
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_ecnpkts, RRDSET_FLAG_DETAIL);

                    rd_cep    = rrddim_add(st_ecnpkts, "InCEPkts",    "CEP",     1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_noectp = rrddim_add(st_ecnpkts, "InNoECTPkts", "NoECTP", -1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_ectp0  = rrddim_add(st_ecnpkts, "InECT0Pkts",  "ECTP0",   1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_ectp1  = rrddim_add(st_ecnpkts, "InECT1Pkts",  "ECTP1",   1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else rrdset_next(st_ecnpkts);

                rrddim_set_by_pointer(st_ecnpkts, rd_cep,    ipext_InCEPkts);
                rrddim_set_by_pointer(st_ecnpkts, rd_noectp, ipext_InNoECTPkts);
                rrddim_set_by_pointer(st_ecnpkts, rd_ectp0,  ipext_InECT0Pkts);
                rrddim_set_by_pointer(st_ecnpkts, rd_ectp1,  ipext_InECT1Pkts);

                rrdset_done(st_ecnpkts);
            }
        }
        else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) {
            size_t h = l++;

            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %zu.", words);
                continue;
            }

            parse_line_pair(ff, arl_tcpext, h, l);

            // --------------------------------------------------------------------

            if(do_tcpext_memory == CONFIG_BOOLEAN_YES || (do_tcpext_memory == CONFIG_BOOLEAN_AUTO && (tcpext_TCPMemoryPressures))) {
                do_tcpext_memory = CONFIG_BOOLEAN_YES;

                static RRDSET *st_tcpmemorypressures = NULL;
                static RRDDIM *rd_pressures = NULL;

                if(unlikely(!st_tcpmemorypressures)) {
                    st_tcpmemorypressures = rrdset_create_localhost(
                            "ipv4"
                            , "tcpmemorypressures"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Memory Pressures"
                            , "events/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP_MEM
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_pressures = rrddim_add(st_tcpmemorypressures, "TCPMemoryPressures",   "pressures",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_tcpmemorypressures);

                rrddim_set_by_pointer(st_tcpmemorypressures, rd_pressures, tcpext_TCPMemoryPressures);

                rrdset_done(st_tcpmemorypressures);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_connaborts == CONFIG_BOOLEAN_YES || (do_tcpext_connaborts == CONFIG_BOOLEAN_AUTO && (tcpext_TCPAbortOnData || tcpext_TCPAbortOnClose || tcpext_TCPAbortOnMemory || tcpext_TCPAbortOnTimeout || tcpext_TCPAbortOnLinger || tcpext_TCPAbortFailed))) {
                do_tcpext_connaborts = CONFIG_BOOLEAN_YES;

                static RRDSET *st_tcpconnaborts = NULL;
                static RRDDIM *rd_baddata = NULL, *rd_userclosed = NULL, *rd_nomemory = NULL, *rd_timeout = NULL, *rd_linger = NULL, *rd_failed = NULL;

                if(unlikely(!st_tcpconnaborts)) {
                    st_tcpconnaborts = rrdset_create_localhost(
                            "ipv4"
                            , "tcpconnaborts"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Connection Aborts"
                            , "connections/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 10
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_baddata    = rrddim_add(st_tcpconnaborts, "TCPAbortOnData",    "baddata",     1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_userclosed = rrddim_add(st_tcpconnaborts, "TCPAbortOnClose",   "userclosed",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_nomemory   = rrddim_add(st_tcpconnaborts, "TCPAbortOnMemory",  "nomemory",    1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_timeout    = rrddim_add(st_tcpconnaborts, "TCPAbortOnTimeout", "timeout",     1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_linger     = rrddim_add(st_tcpconnaborts, "TCPAbortOnLinger",  "linger",      1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_failed     = rrddim_add(st_tcpconnaborts, "TCPAbortFailed",    "failed",     -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_tcpconnaborts);

                rrddim_set_by_pointer(st_tcpconnaborts, rd_baddata,    tcpext_TCPAbortOnData);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_userclosed, tcpext_TCPAbortOnClose);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_nomemory,   tcpext_TCPAbortOnMemory);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_timeout,    tcpext_TCPAbortOnTimeout);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_linger,     tcpext_TCPAbortOnLinger);
                rrddim_set_by_pointer(st_tcpconnaborts, rd_failed,     tcpext_TCPAbortFailed);

                rrdset_done(st_tcpconnaborts);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_reorder == CONFIG_BOOLEAN_YES || (do_tcpext_reorder == CONFIG_BOOLEAN_AUTO && (tcpext_TCPRenoReorder || tcpext_TCPFACKReorder || tcpext_TCPSACKReorder || tcpext_TCPTSReorder))) {
                do_tcpext_reorder = CONFIG_BOOLEAN_YES;

                static RRDSET *st_tcpreorders = NULL;
                static RRDDIM *rd_timestamp = NULL, *rd_sack = NULL, *rd_fack = NULL, *rd_reno = NULL;

                if(unlikely(!st_tcpreorders)) {
                    st_tcpreorders = rrdset_create_localhost(
                            "ipv4"
                            , "tcpreorders"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Reordered Packets by Detection Method"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 20
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_timestamp = rrddim_add(st_tcpreorders, "TCPTSReorder",   "timestamp",   1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_sack      = rrddim_add(st_tcpreorders, "TCPSACKReorder", "sack",        1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_fack      = rrddim_add(st_tcpreorders, "TCPFACKReorder", "fack",        1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_reno      = rrddim_add(st_tcpreorders, "TCPRenoReorder", "reno",        1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_tcpreorders);

                rrddim_set_by_pointer(st_tcpreorders, rd_timestamp, tcpext_TCPTSReorder);
                rrddim_set_by_pointer(st_tcpreorders, rd_sack,      tcpext_TCPSACKReorder);
                rrddim_set_by_pointer(st_tcpreorders, rd_fack,      tcpext_TCPFACKReorder);
                rrddim_set_by_pointer(st_tcpreorders, rd_reno,      tcpext_TCPRenoReorder);

                rrdset_done(st_tcpreorders);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_ofo == CONFIG_BOOLEAN_YES || (do_tcpext_ofo == CONFIG_BOOLEAN_AUTO && (tcpext_TCPOFOQueue || tcpext_TCPOFODrop || tcpext_TCPOFOMerge))) {
                do_tcpext_ofo = CONFIG_BOOLEAN_YES;

                static RRDSET *st_ipv4_tcpofo = NULL;
                static RRDDIM *rd_inqueue = NULL, *rd_dropped = NULL, *rd_merged = NULL, *rd_pruned = NULL;

                if(unlikely(!st_ipv4_tcpofo)) {

                    st_ipv4_tcpofo = rrdset_create_localhost(
                            "ipv4"
                            , "tcpofo"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Out-Of-Order Queue"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 50
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_inqueue = rrddim_add(st_ipv4_tcpofo, "TCPOFOQueue", "inqueue",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_dropped = rrddim_add(st_ipv4_tcpofo, "TCPOFODrop",  "dropped", -1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_merged  = rrddim_add(st_ipv4_tcpofo, "TCPOFOMerge", "merged",   1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_pruned  = rrddim_add(st_ipv4_tcpofo, "OfoPruned",   "pruned",  -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_ipv4_tcpofo);

                rrddim_set_by_pointer(st_ipv4_tcpofo, rd_inqueue, tcpext_TCPOFOQueue);
                rrddim_set_by_pointer(st_ipv4_tcpofo, rd_dropped, tcpext_TCPOFODrop);
                rrddim_set_by_pointer(st_ipv4_tcpofo, rd_merged,  tcpext_TCPOFOMerge);
                rrddim_set_by_pointer(st_ipv4_tcpofo, rd_pruned,  tcpext_OfoPruned);

                rrdset_done(st_ipv4_tcpofo);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_syscookies == CONFIG_BOOLEAN_YES || (do_tcpext_syscookies == CONFIG_BOOLEAN_AUTO && (tcpext_SyncookiesSent || tcpext_SyncookiesRecv || tcpext_SyncookiesFailed))) {
                do_tcpext_syscookies = CONFIG_BOOLEAN_YES;

                static RRDSET *st_syncookies = NULL;
                static RRDDIM *rd_received = NULL, *rd_sent = NULL, *rd_failed = NULL;

                if(unlikely(!st_syncookies)) {

                    st_syncookies = rrdset_create_localhost(
                            "ipv4"
                            , "tcpsyncookies"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP SYN Cookies"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 60
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_received = rrddim_add(st_syncookies, "SyncookiesRecv",   "received",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_sent     = rrddim_add(st_syncookies, "SyncookiesSent",   "sent",     -1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_failed   = rrddim_add(st_syncookies, "SyncookiesFailed", "failed",   -1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_syncookies);

                rrddim_set_by_pointer(st_syncookies, rd_received, tcpext_SyncookiesRecv);
                rrddim_set_by_pointer(st_syncookies, rd_sent,     tcpext_SyncookiesSent);
                rrddim_set_by_pointer(st_syncookies, rd_failed,   tcpext_SyncookiesFailed);

                rrdset_done(st_syncookies);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_listen == CONFIG_BOOLEAN_YES || (do_tcpext_listen == CONFIG_BOOLEAN_AUTO && (tcpext_ListenOverflows || tcpext_ListenDrops))) {
                do_tcpext_listen = CONFIG_BOOLEAN_YES;

                static RRDSET *st_listen = NULL;
                static RRDDIM *rd_overflows = NULL, *rd_drops = NULL;

                if(unlikely(!st_listen)) {

                    st_listen = rrdset_create_localhost(
                            "ipv4"
                            , "tcplistenissues"
                            , NULL
                            , "tcp"
                            , NULL
                            , "TCP Listen Socket Issues"
                            , "packets/s"
                            , "proc"
                            , "net/netstat"
                            , NETDATA_CHART_PRIO_IPV4_TCP + 15
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_overflows = rrddim_add(st_listen, "ListenOverflows", "overflows",  1, 1, RRD_ALGORITHM_INCREMENTAL);
                    rd_drops     = rrddim_add(st_listen, "ListenDrops",     "drops",      1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else
                    rrdset_next(st_listen);

                rrddim_set_by_pointer(st_listen, rd_overflows, tcpext_ListenOverflows);
                rrddim_set_by_pointer(st_listen, rd_drops,     tcpext_ListenDrops);

                rrdset_done(st_listen);
            }
        }
    }

    return 0;
}
コード例 #15
0
ファイル: proc_stat.c プロジェクト: firehol/netdata
int do_proc_stat(int update_every, usec_t dt) {
    (void)dt;

    static struct cpu_chart *all_cpu_charts = NULL;
    static size_t all_cpu_charts_size = 0;
    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,
           do_core_throttle_count = -1, do_package_throttle_count = -1, do_cpu_freq = -1, do_cpuidle = -1;
    static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked;
    static char *core_throttle_count_filename = NULL, *package_throttle_count_filename = NULL, *scaling_cur_freq_filename = NULL,
           *time_in_state_filename = NULL, *schedstat_filename = NULL, *cpuidle_name_filename = NULL, *cpuidle_time_filename = NULL;
    static RRDVAR *cpus_var = NULL;
    static int accurate_freq_avail = 0, accurate_freq_is_used = 0;
    size_t cores_found = (size_t)processors;

    if(unlikely(do_cpu == -1)) {
        do_cpu                    = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", CONFIG_BOOLEAN_YES);
        do_cpu_cores              = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", CONFIG_BOOLEAN_YES);
        do_interrupts             = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", CONFIG_BOOLEAN_YES);
        do_context                = config_get_boolean("plugin:proc:/proc/stat", "context switches", CONFIG_BOOLEAN_YES);
        do_forks                  = config_get_boolean("plugin:proc:/proc/stat", "processes started", CONFIG_BOOLEAN_YES);
        do_processes              = config_get_boolean("plugin:proc:/proc/stat", "processes running", CONFIG_BOOLEAN_YES);

        // give sane defaults based on the number of processors
        if(unlikely(processors > 50)) {
            // the system has too many processors
            keep_per_core_fds_open = CONFIG_BOOLEAN_NO;
            do_core_throttle_count = CONFIG_BOOLEAN_NO;
            do_package_throttle_count = CONFIG_BOOLEAN_NO;
            do_cpu_freq = CONFIG_BOOLEAN_NO;
            do_cpuidle = CONFIG_BOOLEAN_NO;
        }
        else {
            // the system has a reasonable number of processors
            keep_per_core_fds_open = CONFIG_BOOLEAN_YES;
            do_core_throttle_count = CONFIG_BOOLEAN_AUTO;
            do_package_throttle_count = CONFIG_BOOLEAN_NO;
            do_cpu_freq = CONFIG_BOOLEAN_YES;
            do_cpuidle = CONFIG_BOOLEAN_YES;
        }
        if(unlikely(processors > 24)) {
            // the system has too many processors
            keep_cpuidle_fds_open = CONFIG_BOOLEAN_NO;
        }
        else {
            // the system has a reasonable number of processors
            keep_cpuidle_fds_open = CONFIG_BOOLEAN_YES;
        }

        keep_per_core_fds_open    = config_get_boolean("plugin:proc:/proc/stat", "keep per core files open", keep_per_core_fds_open);
        keep_cpuidle_fds_open     = config_get_boolean("plugin:proc:/proc/stat", "keep cpuidle files open", keep_cpuidle_fds_open);
        do_core_throttle_count    = config_get_boolean_ondemand("plugin:proc:/proc/stat", "core_throttle_count", do_core_throttle_count);
        do_package_throttle_count = config_get_boolean_ondemand("plugin:proc:/proc/stat", "package_throttle_count", do_package_throttle_count);
        do_cpu_freq               = config_get_boolean_ondemand("plugin:proc:/proc/stat", "cpu frequency", do_cpu_freq);
        do_cpuidle                = config_get_boolean_ondemand("plugin:proc:/proc/stat", "cpu idle states", do_cpuidle);

        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");

        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/thermal_throttle/core_throttle_count");
        core_throttle_count_filename = config_get("plugin:proc:/proc/stat", "core_throttle_count filename to monitor", filename);

        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/thermal_throttle/package_throttle_count");
        package_throttle_count_filename = config_get("plugin:proc:/proc/stat", "package_throttle_count filename to monitor", filename);

        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/cpufreq/scaling_cur_freq");
        scaling_cur_freq_filename = config_get("plugin:proc:/proc/stat", "scaling_cur_freq filename to monitor", filename);

        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/cpufreq/stats/time_in_state");
        time_in_state_filename = config_get("plugin:proc:/proc/stat", "time_in_state filename to monitor", filename);

        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/schedstat");
        schedstat_filename = config_get("plugin:proc:/proc/stat", "schedstat filename to monitor", filename);

        if(do_cpuidle != CONFIG_BOOLEAN_NO) {
            struct stat stbuf;

            if (stat(schedstat_filename, &stbuf))
                do_cpuidle = CONFIG_BOOLEAN_NO;
        }

        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/cpu%zu/cpuidle/state%zu/name");
        cpuidle_name_filename = config_get("plugin:proc:/proc/stat", "cpuidle name filename to monitor", filename);

        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/cpu%zu/cpuidle/state%zu/time");
        cpuidle_time_filename = config_get("plugin:proc:/proc/stat", "cpuidle time filename to monitor", filename);
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_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

    size_t lines = procfile_lines(ff), l;
    size_t words;

    unsigned long long processes = 0, running = 0 , blocked = 0;

    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 %zu.", words);
                continue;
            }

            size_t core    = (row_key[3] == '\0') ? 0 : str2ul(&row_key[3]) + 1;
            if(likely(core > 0)) cores_found = core;

            if(likely((core == 0 && do_cpu) || (core > 0 && do_cpu_cores))) {
                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        = str2ull(procfile_lineword(ff, l, 1));
                nice        = str2ull(procfile_lineword(ff, l, 2));
                system      = str2ull(procfile_lineword(ff, l, 3));
                idle        = str2ull(procfile_lineword(ff, l, 4));
                iowait      = str2ull(procfile_lineword(ff, l, 5));
                irq         = str2ull(procfile_lineword(ff, l, 6));
                softirq     = str2ull(procfile_lineword(ff, l, 7));
                steal       = str2ull(procfile_lineword(ff, l, 8));

                guest       = str2ull(procfile_lineword(ff, l, 9));
                user -= guest;

                guest_nice  = str2ull(procfile_lineword(ff, l, 10));
                nice -= guest_nice;

                char *title, *type, *context, *family;
                long priority;

                if(unlikely(core >= all_cpu_charts_size)) {
                    size_t old_cpu_charts_size = all_cpu_charts_size;
                    all_cpu_charts_size = core + 1;
                    all_cpu_charts = reallocz(all_cpu_charts, sizeof(struct cpu_chart) * all_cpu_charts_size);
                    memset(&all_cpu_charts[old_cpu_charts_size], 0, sizeof(struct cpu_chart) * (all_cpu_charts_size - old_cpu_charts_size));
                }
                struct cpu_chart *cpu_chart = &all_cpu_charts[core];

                if(unlikely(!cpu_chart->st)) {
                    cpu_chart->id = strdupz(id);

                    if(unlikely(core == 0)) {
                        title = "Total CPU utilization";
                        type = "system";
                        context = "system.cpu";
                        family = id;
                        priority = NETDATA_CHART_PRIO_SYSTEM_CPU;
                    }
                    else {
                        title = "Core utilization";
                        type = "cpu";
                        context = "cpu.cpu";
                        family = "utilization";
                        priority = NETDATA_CHART_PRIO_CPU_PER_CORE;

                        char filename[FILENAME_MAX + 1];
                        struct stat stbuf;

                        if(do_core_throttle_count != CONFIG_BOOLEAN_NO) {
                            snprintfz(filename, FILENAME_MAX, core_throttle_count_filename, id);
                            if (stat(filename, &stbuf) == 0) {
                                cpu_chart->files[CORE_THROTTLE_COUNT_INDEX].filename = strdupz(filename);
                                cpu_chart->files[CORE_THROTTLE_COUNT_INDEX].fd = -1;
                                do_core_throttle_count = CONFIG_BOOLEAN_YES;
                            }
                        }

                        if(do_package_throttle_count != CONFIG_BOOLEAN_NO) {
                            snprintfz(filename, FILENAME_MAX, package_throttle_count_filename, id);
                            if (stat(filename, &stbuf) == 0) {
                                cpu_chart->files[PACKAGE_THROTTLE_COUNT_INDEX].filename = strdupz(filename);
                                cpu_chart->files[PACKAGE_THROTTLE_COUNT_INDEX].fd = -1;
                                do_package_throttle_count = CONFIG_BOOLEAN_YES;
                            }
                        }

                        if(do_cpu_freq != CONFIG_BOOLEAN_NO) {

                            snprintfz(filename, FILENAME_MAX, scaling_cur_freq_filename, id);

                            if (stat(filename, &stbuf) == 0) {
                                cpu_chart->files[CPU_FREQ_INDEX].filename = strdupz(filename);
                                cpu_chart->files[CPU_FREQ_INDEX].fd = -1;
                                do_cpu_freq = CONFIG_BOOLEAN_YES;
                            }

                            snprintfz(filename, FILENAME_MAX, time_in_state_filename, id);

                            if (stat(filename, &stbuf) == 0) {
                                cpu_chart->time_in_state_files.filename = strdupz(filename);
                                cpu_chart->time_in_state_files.ff = NULL;
                                do_cpu_freq = CONFIG_BOOLEAN_YES;
                                accurate_freq_avail = 1;
                            }
                        }
                    }

                    cpu_chart->st = rrdset_create_localhost(
                            type
                            , id
                            , NULL
                            , family
                            , context
                            , title
                            , "percentage"
                            , PLUGIN_PROC_NAME
                            , PLUGIN_PROC_MODULE_STAT_NAME
                            , priority + core
                            , update_every
                            , RRDSET_TYPE_STACKED
                    );

                    long multiplier = 1;
                    long divisor = 1; // sysconf(_SC_CLK_TCK);

                    cpu_chart->rd_guest_nice = rrddim_add(cpu_chart->st, "guest_nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_guest      = rrddim_add(cpu_chart->st, "guest",      NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_steal      = rrddim_add(cpu_chart->st, "steal",      NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_softirq    = rrddim_add(cpu_chart->st, "softirq",    NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_irq        = rrddim_add(cpu_chart->st, "irq",        NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_user       = rrddim_add(cpu_chart->st, "user",       NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_system     = rrddim_add(cpu_chart->st, "system",     NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_nice       = rrddim_add(cpu_chart->st, "nice",       NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_iowait     = rrddim_add(cpu_chart->st, "iowait",     NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_idle       = rrddim_add(cpu_chart->st, "idle",       NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    rrddim_hide(cpu_chart->st, "idle");

                    if(unlikely(core == 0 && cpus_var == NULL))
                        cpus_var = rrdvar_custom_host_variable_create(localhost, "active_processors");
                }
                else rrdset_next(cpu_chart->st);

                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_user, user);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_nice, nice);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_system, system);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_idle, idle);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_iowait, iowait);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_irq, irq);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_softirq, softirq);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_steal, steal);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_guest, guest);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_guest_nice, guest_nice);
                rrdset_done(cpu_chart->st);
            }
        }
        else if(unlikely(hash == hash_intr && strcmp(row_key, "intr") == 0)) {
            if(likely(do_interrupts)) {
                static RRDSET *st_intr = NULL;
                static RRDDIM *rd_interrupts = NULL;
                unsigned long long value = str2ull(procfile_lineword(ff, l, 1));

                if(unlikely(!st_intr)) {
                    st_intr = rrdset_create_localhost(
                            "system"
                            , "intr"
                            , NULL
                            , "interrupts"
                            , NULL
                            , "CPU Interrupts"
                            , "interrupts/s"
                            , PLUGIN_PROC_NAME
                            , PLUGIN_PROC_MODULE_STAT_NAME
                            , NETDATA_CHART_PRIO_SYSTEM_INTR
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_intr, RRDSET_FLAG_DETAIL);

                    rd_interrupts = rrddim_add(st_intr, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else rrdset_next(st_intr);

                rrddim_set_by_pointer(st_intr, rd_interrupts, value);
                rrdset_done(st_intr);
            }
        }
        else if(unlikely(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0)) {
            if(likely(do_context)) {
                static RRDSET *st_ctxt = NULL;
                static RRDDIM *rd_switches = NULL;
                unsigned long long value = str2ull(procfile_lineword(ff, l, 1));

                if(unlikely(!st_ctxt)) {
                    st_ctxt = rrdset_create_localhost(
                            "system"
                            , "ctxt"
                            , NULL
                            , "processes"
                            , NULL
                            , "CPU Context Switches"
                            , "context switches/s"
                            , PLUGIN_PROC_NAME
                            , PLUGIN_PROC_MODULE_STAT_NAME
                            , NETDATA_CHART_PRIO_SYSTEM_CTXT
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_switches = rrddim_add(st_ctxt, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else rrdset_next(st_ctxt);

                rrddim_set_by_pointer(st_ctxt, rd_switches, value);
                rrdset_done(st_ctxt);
            }
        }
        else if(unlikely(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0)) {
            processes = str2ull(procfile_lineword(ff, l, 1));
        }
        else if(unlikely(hash == hash_procs_running && !running && strcmp(row_key, "procs_running") == 0)) {
            running = str2ull(procfile_lineword(ff, l, 1));
        }
        else if(unlikely(hash == hash_procs_blocked && !blocked && strcmp(row_key, "procs_blocked") == 0)) {
            blocked = str2ull(procfile_lineword(ff, l, 1));
        }
    }

    // --------------------------------------------------------------------

    if(likely(do_forks)) {
        static RRDSET *st_forks = NULL;
        static RRDDIM *rd_started = NULL;

        if(unlikely(!st_forks)) {
            st_forks = rrdset_create_localhost(
                    "system"
                    , "forks"
                    , NULL
                    , "processes"
                    , NULL
                    , "Started Processes"
                    , "processes/s"
                    , PLUGIN_PROC_NAME
                    , PLUGIN_PROC_MODULE_STAT_NAME
                    , NETDATA_CHART_PRIO_SYSTEM_FORKS
                    , update_every
                    , RRDSET_TYPE_LINE
            );
            rrdset_flag_set(st_forks, RRDSET_FLAG_DETAIL);

            rd_started = rrddim_add(st_forks, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
        }
        else rrdset_next(st_forks);

        rrddim_set_by_pointer(st_forks, rd_started, processes);
        rrdset_done(st_forks);
    }

    // --------------------------------------------------------------------

    if(likely(do_processes)) {
        static RRDSET *st_processes = NULL;
        static RRDDIM *rd_running = NULL;
        static RRDDIM *rd_blocked = NULL;

        if(unlikely(!st_processes)) {
            st_processes = rrdset_create_localhost(
                    "system"
                    , "processes"
                    , NULL
                    , "processes"
                    , NULL
                    , "System Processes"
                    , "processes"
                    , PLUGIN_PROC_NAME
                    , PLUGIN_PROC_MODULE_STAT_NAME
                    , NETDATA_CHART_PRIO_SYSTEM_PROCESSES
                    , update_every
                    , RRDSET_TYPE_LINE
            );

            rd_running = rrddim_add(st_processes, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
            rd_blocked = rrddim_add(st_processes, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
        }
        else rrdset_next(st_processes);

        rrddim_set_by_pointer(st_processes, rd_running, running);
        rrddim_set_by_pointer(st_processes, rd_blocked, blocked);
        rrdset_done(st_processes);
    }

    if(likely(all_cpu_charts_size > 1)) {
        if(likely(do_core_throttle_count != CONFIG_BOOLEAN_NO)) {
            int r = read_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CORE_THROTTLE_COUNT_INDEX);
            if(likely(r != -1 && (do_core_throttle_count == CONFIG_BOOLEAN_YES || r > 0))) {
                do_core_throttle_count = CONFIG_BOOLEAN_YES;

                static RRDSET *st_core_throttle_count = NULL;

                if (unlikely(!st_core_throttle_count))
                    st_core_throttle_count = rrdset_create_localhost(
                            "cpu"
                            , "core_throttling"
                            , NULL
                            , "throttling"
                            , "cpu.core_throttling"
                            , "Core Thermal Throttling Events"
                            , "events/s"
                            , PLUGIN_PROC_NAME
                            , PLUGIN_PROC_MODULE_STAT_NAME
                            , NETDATA_CHART_PRIO_CORE_THROTTLING
                            , update_every
                            , RRDSET_TYPE_LINE
                    );
                else
                    rrdset_next(st_core_throttle_count);

                chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CORE_THROTTLE_COUNT_INDEX, st_core_throttle_count, 1, 1, RRD_ALGORITHM_INCREMENTAL);
                rrdset_done(st_core_throttle_count);
            }
        }

        if(likely(do_package_throttle_count != CONFIG_BOOLEAN_NO)) {
            int r = read_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, PACKAGE_THROTTLE_COUNT_INDEX);
            if(likely(r != -1 && (do_package_throttle_count == CONFIG_BOOLEAN_YES || r > 0))) {
                do_package_throttle_count = CONFIG_BOOLEAN_YES;

                static RRDSET *st_package_throttle_count = NULL;

                if(unlikely(!st_package_throttle_count))
                    st_package_throttle_count = rrdset_create_localhost(
                            "cpu"
                            , "package_throttling"
                            , NULL
                            , "throttling"
                            , "cpu.package_throttling"
                            , "Package Thermal Throttling Events"
                            , "events/s"
                            , PLUGIN_PROC_NAME
                            , PLUGIN_PROC_MODULE_STAT_NAME
                            , NETDATA_CHART_PRIO_PACKAGE_THROTTLING
                            , update_every
                            , RRDSET_TYPE_LINE
                    );
                else
                    rrdset_next(st_package_throttle_count);

                chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, PACKAGE_THROTTLE_COUNT_INDEX, st_package_throttle_count, 1, 1, RRD_ALGORITHM_INCREMENTAL);
                rrdset_done(st_package_throttle_count);
            }
        }

        if(likely(do_cpu_freq != CONFIG_BOOLEAN_NO)) {
            char filename[FILENAME_MAX + 1];
            int r = 0;

            if (accurate_freq_avail) {
                r = read_per_core_time_in_state_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CPU_FREQ_INDEX);
                if(r > 0 && !accurate_freq_is_used) {
                    accurate_freq_is_used = 1;
                    snprintfz(filename, FILENAME_MAX, time_in_state_filename, "cpu*");
                    info("cpufreq is using %s", filename);
                }
            }
            if (r < 1) {
                r = read_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CPU_FREQ_INDEX);
                if(accurate_freq_is_used) {
                    accurate_freq_is_used = 0;
                    snprintfz(filename, FILENAME_MAX, scaling_cur_freq_filename, "cpu*");
                    info("cpufreq fell back to %s", filename);
                }
            }

            if(likely(r != -1 && (do_cpu_freq == CONFIG_BOOLEAN_YES || r > 0))) {
                do_cpu_freq = CONFIG_BOOLEAN_YES;

                static RRDSET *st_scaling_cur_freq = NULL;

                if(unlikely(!st_scaling_cur_freq))
                    st_scaling_cur_freq = rrdset_create_localhost(
                            "cpu"
                            , "cpufreq"
                            , NULL
                            , "cpufreq"
                            , "cpufreq.cpufreq"
                            , "Current CPU Frequency"
                            , "MHz"
                            , PLUGIN_PROC_NAME
                            , PLUGIN_PROC_MODULE_STAT_NAME
                            , NETDATA_CHART_PRIO_CPUFREQ_SCALING_CUR_FREQ
                            , update_every
                            , RRDSET_TYPE_LINE
                    );
                else
                    rrdset_next(st_scaling_cur_freq);

                chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CPU_FREQ_INDEX, st_scaling_cur_freq, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
                rrdset_done(st_scaling_cur_freq);
            }
        }
    }

    // --------------------------------------------------------------------

    static struct per_core_cpuidle_chart *cpuidle_charts = NULL;
    size_t schedstat_cores_found = 0;

    if(likely(do_cpuidle != CONFIG_BOOLEAN_NO && !read_schedstat(schedstat_filename, &cpuidle_charts, &schedstat_cores_found))) {
        int cpu_states_updated = 0;
        size_t core, state;


        // proc.plugin runs on Linux systems only. Multi-platform compatibility is not needed here,
        // so bare pthread functions are used to avoid unneeded overheads.
        for(core = 0; core < schedstat_cores_found; core++) {
            if(unlikely(!(cpuidle_charts[core].active_time - cpuidle_charts[core].last_active_time))) {
                pthread_t thread;

                if(unlikely(pthread_create(&thread, NULL, wake_cpu_thread, (void *)&core)))
                    error("Cannot create wake_cpu_thread");
                else if(unlikely(pthread_join(thread, NULL)))
                    error("Cannot join wake_cpu_thread");
                cpu_states_updated = 1;
            }
        }

        if(unlikely(!cpu_states_updated || !read_schedstat(schedstat_filename, &cpuidle_charts, &schedstat_cores_found))) {
            for(core = 0; core < schedstat_cores_found; core++) {
                cpuidle_charts[core].last_active_time = cpuidle_charts[core].active_time;

                int r = read_cpuidle_states(cpuidle_name_filename, cpuidle_time_filename, cpuidle_charts, core);
                if(likely(r != -1 && (do_cpuidle == CONFIG_BOOLEAN_YES || r > 0))) {
                    do_cpuidle = CONFIG_BOOLEAN_YES;

                    char cpuidle_chart_id[RRD_ID_LENGTH_MAX + 1];
                    snprintfz(cpuidle_chart_id, RRD_ID_LENGTH_MAX, "cpu%zu_cpuidle", core);

                    if(unlikely(!cpuidle_charts[core].st)) {
                        cpuidle_charts[core].st = rrdset_create_localhost(
                                "cpu"
                                , cpuidle_chart_id
                                , NULL
                                , "cpuidle"
                                , "cpuidle.cpuidle"
                                , "C-state residency time"
                                , "percentage"
                                , PLUGIN_PROC_NAME
                                , PLUGIN_PROC_MODULE_STAT_NAME
                                , NETDATA_CHART_PRIO_CPUIDLE + core
                                , update_every
                                , RRDSET_TYPE_STACKED
                        );

                        char cpuidle_dim_id[RRD_ID_LENGTH_MAX + 1];
                        snprintfz(cpuidle_dim_id, RRD_ID_LENGTH_MAX, "cpu%zu_active_time", core);
                        cpuidle_charts[core].active_time_rd = rrddim_add(cpuidle_charts[core].st, cpuidle_dim_id, "C0 (active)", 1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                        for(state = 0; state < cpuidle_charts[core].cpuidle_state_len; state++) {
                            snprintfz(cpuidle_dim_id, RRD_ID_LENGTH_MAX, "cpu%zu_cpuidle_state%zu_time", core, state);
                            cpuidle_charts[core].cpuidle_state[state].rd = rrddim_add(cpuidle_charts[core].st, cpuidle_dim_id,
                                                                                      cpuidle_charts[core].cpuidle_state[state].name,
                                                                                      1, 1, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                        }
                    }
                    else
                        rrdset_next(cpuidle_charts[core].st);

                    rrddim_set_by_pointer(cpuidle_charts[core].st, cpuidle_charts[core].active_time_rd, cpuidle_charts[core].active_time);
                    for(state = 0; state < cpuidle_charts[core].cpuidle_state_len; state++) {
                        rrddim_set_by_pointer(cpuidle_charts[core].st, cpuidle_charts[core].cpuidle_state[state].rd, cpuidle_charts[core].cpuidle_state[state].value);
                    }
                    rrdset_done(cpuidle_charts[core].st);
                }
            }
        }
    }

    if(cpus_var)
        rrdvar_custom_host_variable_set(localhost, cpus_var, cores_found);

    return 0;
}
コード例 #16
0
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;
}
コード例 #17
0
ファイル: proc_interrupts.c プロジェクト: tferreira/netdata
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;
}
コード例 #18
0
ファイル: proc_stat.c プロジェクト: tvieira/netdata
int do_proc_stat(int update_every, usec_t dt) {
    (void)dt;

    static struct cpu_chart *all_cpu_charts = NULL;
    static size_t all_cpu_charts_size = 0;
    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, do_core_throttle_count = -1, do_package_throttle_count = -1, do_scaling_cur_freq = -1;
    static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked;
    static char *core_throttle_count_filename = NULL, *package_throttle_count_filename = NULL, *scaling_cur_freq_filename = NULL;

    if(unlikely(do_cpu == -1)) {
        do_cpu                    = config_get_boolean("plugin:proc:/proc/stat", "cpu utilization", CONFIG_BOOLEAN_YES);
        do_cpu_cores              = config_get_boolean("plugin:proc:/proc/stat", "per cpu core utilization", CONFIG_BOOLEAN_YES);
        do_interrupts             = config_get_boolean("plugin:proc:/proc/stat", "cpu interrupts", CONFIG_BOOLEAN_YES);
        do_context                = config_get_boolean("plugin:proc:/proc/stat", "context switches", CONFIG_BOOLEAN_YES);
        do_forks                  = config_get_boolean("plugin:proc:/proc/stat", "processes started", CONFIG_BOOLEAN_YES);
        do_processes              = config_get_boolean("plugin:proc:/proc/stat", "processes running", CONFIG_BOOLEAN_YES);

        // give sane defaults based on the number of processors
        if(processors > 50) {
            // the system has too many processors
            keep_per_core_fds_open = CONFIG_BOOLEAN_NO;
            do_core_throttle_count = CONFIG_BOOLEAN_NO;
            do_package_throttle_count = CONFIG_BOOLEAN_NO;
            do_scaling_cur_freq = CONFIG_BOOLEAN_NO;
        }
        else {
            // the system has a reasonable number of processors
            keep_per_core_fds_open = CONFIG_BOOLEAN_YES;
            do_core_throttle_count = CONFIG_BOOLEAN_AUTO;
            do_package_throttle_count = CONFIG_BOOLEAN_NO;
            do_scaling_cur_freq = CONFIG_BOOLEAN_NO;
        }

        keep_per_core_fds_open    = config_get_boolean("plugin:proc:/proc/stat", "keep per core files open", keep_per_core_fds_open);
        do_core_throttle_count    = config_get_boolean_ondemand("plugin:proc:/proc/stat", "core_throttle_count", do_core_throttle_count);
        do_package_throttle_count = config_get_boolean_ondemand("plugin:proc:/proc/stat", "package_throttle_count", do_package_throttle_count);
        do_scaling_cur_freq       = config_get_boolean_ondemand("plugin:proc:/proc/stat", "scaling_cur_freq", do_scaling_cur_freq);

        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");

        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/thermal_throttle/core_throttle_count");
        core_throttle_count_filename = config_get("plugin:proc:/proc/stat", "core_throttle_count filename to monitor", filename);

        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/thermal_throttle/package_throttle_count");
        package_throttle_count_filename = config_get("plugin:proc:/proc/stat", "package_throttle_count filename to monitor", filename);

        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/devices/system/cpu/%s/cpufreq/scaling_cur_freq");
        scaling_cur_freq_filename = config_get("plugin:proc:/proc/stat", "scaling_cur_freq filename to monitor", filename);
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_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

    size_t lines = procfile_lines(ff), l;
    size_t words;

    unsigned long long processes = 0, running = 0 , blocked = 0;

    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 %zu.", words);
                continue;
            }

            size_t core    = (row_key[3] == '\0') ? 0 : str2ul(&row_key[3]) + 1;

            if(likely((core == 0 && do_cpu) || (core > 0 && do_cpu_cores))) {
                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        = str2ull(procfile_lineword(ff, l, 1));
                nice        = str2ull(procfile_lineword(ff, l, 2));
                system      = str2ull(procfile_lineword(ff, l, 3));
                idle        = str2ull(procfile_lineword(ff, l, 4));
                iowait      = str2ull(procfile_lineword(ff, l, 5));
                irq         = str2ull(procfile_lineword(ff, l, 6));
                softirq     = str2ull(procfile_lineword(ff, l, 7));
                steal       = str2ull(procfile_lineword(ff, l, 8));

                guest       = str2ull(procfile_lineword(ff, l, 9));
                user -= guest;

                guest_nice  = str2ull(procfile_lineword(ff, l, 10));
                nice -= guest_nice;

                char *title, *type, *context, *family;
                long priority;

                if(core >= all_cpu_charts_size) {
                    size_t old_cpu_charts_size = all_cpu_charts_size;
                    all_cpu_charts_size = core + 1;
                    all_cpu_charts = reallocz(all_cpu_charts, sizeof(struct cpu_chart) * all_cpu_charts_size);
                    memset(&all_cpu_charts[old_cpu_charts_size], 0, sizeof(struct cpu_chart) * (all_cpu_charts_size - old_cpu_charts_size));
                }
                struct cpu_chart *cpu_chart = &all_cpu_charts[core];

                if(unlikely(!cpu_chart->st)) {
                    cpu_chart->id = strdupz(id);

                    if(core == 0) {
                        title = "Total CPU utilization";
                        type = "system";
                        context = "system.cpu";
                        family = id;
                        priority = 100;
                    }
                    else {
                        title = "Core utilization";
                        type = "cpu";
                        context = "cpu.cpu";
                        family = "utilization";
                        priority = 1000;

                        // FIXME: check for /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq
                        // FIXME: check for /sys/devices/system/cpu/cpu*/cpufreq/stats/time_in_state

                        char filename[FILENAME_MAX + 1];
                        struct stat stbuf;

                        if(do_core_throttle_count != CONFIG_BOOLEAN_NO) {
                            snprintfz(filename, FILENAME_MAX, core_throttle_count_filename, id);
                            if (stat(filename, &stbuf) == 0) {
                                cpu_chart->files[CORE_THROTTLE_COUNT_INDEX].filename = strdupz(filename);
                                cpu_chart->files[CORE_THROTTLE_COUNT_INDEX].fd = -1;
                                do_core_throttle_count = CONFIG_BOOLEAN_YES;
                            }
                        }

                        if(do_package_throttle_count != CONFIG_BOOLEAN_NO) {
                            snprintfz(filename, FILENAME_MAX, package_throttle_count_filename, id);
                            if (stat(filename, &stbuf) == 0) {
                                cpu_chart->files[PACKAGE_THROTTLE_COUNT_INDEX].filename = strdupz(filename);
                                cpu_chart->files[PACKAGE_THROTTLE_COUNT_INDEX].fd = -1;
                                do_package_throttle_count = CONFIG_BOOLEAN_YES;
                            }
                        }

                        if(do_scaling_cur_freq != CONFIG_BOOLEAN_NO) {
                            snprintfz(filename, FILENAME_MAX, scaling_cur_freq_filename, id);
                            if (stat(filename, &stbuf) == 0) {
                                cpu_chart->files[SCALING_CUR_FREQ_INDEX].filename = strdupz(filename);
                                cpu_chart->files[SCALING_CUR_FREQ_INDEX].fd = -1;
                                do_scaling_cur_freq = CONFIG_BOOLEAN_YES;
                            }
                        }
                    }

                    cpu_chart->st = rrdset_create_localhost(
                            type
                            , id
                            , NULL
                            , family
                            , context
                            , title
                            , "percentage"
                            , "proc"
                            , "stat"
                            , priority
                            , update_every
                            , RRDSET_TYPE_STACKED
                    );

                    long multiplier = 1;
                    long divisor = 1; // sysconf(_SC_CLK_TCK);

                    cpu_chart->rd_guest_nice = rrddim_add(cpu_chart->st, "guest_nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_guest      = rrddim_add(cpu_chart->st, "guest",      NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_steal      = rrddim_add(cpu_chart->st, "steal",      NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_softirq    = rrddim_add(cpu_chart->st, "softirq",    NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_irq        = rrddim_add(cpu_chart->st, "irq",        NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_user       = rrddim_add(cpu_chart->st, "user",       NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_system     = rrddim_add(cpu_chart->st, "system",     NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_nice       = rrddim_add(cpu_chart->st, "nice",       NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_iowait     = rrddim_add(cpu_chart->st, "iowait",     NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    cpu_chart->rd_idle       = rrddim_add(cpu_chart->st, "idle",       NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
                    rrddim_hide(cpu_chart->st, "idle");
                }
                else rrdset_next(cpu_chart->st);

                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_user, user);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_nice, nice);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_system, system);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_idle, idle);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_iowait, iowait);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_irq, irq);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_softirq, softirq);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_steal, steal);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_guest, guest);
                rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_guest_nice, guest_nice);
                rrdset_done(cpu_chart->st);
            }
        }
        else if(unlikely(hash == hash_intr && strcmp(row_key, "intr") == 0)) {
            if(likely(do_interrupts)) {
                static RRDSET *st_intr = NULL;
                static RRDDIM *rd_interrupts = NULL;
                unsigned long long value = str2ull(procfile_lineword(ff, l, 1));

                if(unlikely(!st_intr)) {
                    st_intr = rrdset_create_localhost(
                            "system"
                            , "intr"
                            , NULL
                            , "interrupts"
                            , NULL
                            , "CPU Interrupts"
                            , "interrupts/s"
                            , "proc"
                            , "stat"
                            , 900
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rrdset_flag_set(st_intr, RRDSET_FLAG_DETAIL);

                    rd_interrupts = rrddim_add(st_intr, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else rrdset_next(st_intr);

                rrddim_set_by_pointer(st_intr, rd_interrupts, value);
                rrdset_done(st_intr);
            }
        }
        else if(unlikely(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0)) {
            if(likely(do_context)) {
                static RRDSET *st_ctxt = NULL;
                static RRDDIM *rd_switches = NULL;
                unsigned long long value = str2ull(procfile_lineword(ff, l, 1));

                if(unlikely(!st_ctxt)) {
                    st_ctxt = rrdset_create_localhost(
                            "system"
                            , "ctxt"
                            , NULL
                            , "processes"
                            , NULL
                            , "CPU Context Switches"
                            , "context switches/s"
                            , "proc"
                            , "stat"
                            , 800
                            , update_every
                            , RRDSET_TYPE_LINE
                    );

                    rd_switches = rrddim_add(st_ctxt, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
                }
                else rrdset_next(st_ctxt);

                rrddim_set_by_pointer(st_ctxt, rd_switches, value);
                rrdset_done(st_ctxt);
            }
        }
        else if(unlikely(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0)) {
            processes = str2ull(procfile_lineword(ff, l, 1));
        }
        else if(unlikely(hash == hash_procs_running && !running && strcmp(row_key, "procs_running") == 0)) {
            running = str2ull(procfile_lineword(ff, l, 1));
        }
        else if(unlikely(hash == hash_procs_blocked && !blocked && strcmp(row_key, "procs_blocked") == 0)) {
            blocked = str2ull(procfile_lineword(ff, l, 1));
        }
    }

    // --------------------------------------------------------------------

    if(likely(do_forks)) {
        static RRDSET *st_forks = NULL;
        static RRDDIM *rd_started = NULL;

        if(unlikely(!st_forks)) {
            st_forks = rrdset_create_localhost(
                    "system"
                    , "forks"
                    , NULL
                    , "processes"
                    , NULL
                    , "Started Processes"
                    , "processes/s"
                    , "proc"
                    , "stat"
                    , 700
                    , update_every
                    , RRDSET_TYPE_LINE
            );
            rrdset_flag_set(st_forks, RRDSET_FLAG_DETAIL);

            rd_started = rrddim_add(st_forks, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
        }
        else rrdset_next(st_forks);

        rrddim_set_by_pointer(st_forks, rd_started, processes);
        rrdset_done(st_forks);
    }

    // --------------------------------------------------------------------

    if(likely(do_processes)) {
        static RRDSET *st_processes = NULL;
        static RRDDIM *rd_running = NULL;
        static RRDDIM *rd_blocked = NULL;

        if(unlikely(!st_processes)) {
            st_processes = rrdset_create_localhost(
                    "system"
                    , "processes"
                    , NULL
                    , "processes"
                    , NULL
                    , "System Processes"
                    , "processes"
                    , "proc"
                    , "stat"
                    , 600
                    , update_every
                    , RRDSET_TYPE_LINE
            );

            rd_running = rrddim_add(st_processes, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
            rd_blocked = rrddim_add(st_processes, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
        }
        else rrdset_next(st_processes);

        rrddim_set_by_pointer(st_processes, rd_running, running);
        rrddim_set_by_pointer(st_processes, rd_blocked, blocked);
        rrdset_done(st_processes);
    }

    if(likely(all_cpu_charts_size > 1)) {
        if(likely(do_core_throttle_count != CONFIG_BOOLEAN_NO)) {
            int r = read_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CORE_THROTTLE_COUNT_INDEX);
            if(likely(r != -1 && (do_core_throttle_count == CONFIG_BOOLEAN_YES || r > 0))) {
                do_core_throttle_count = CONFIG_BOOLEAN_YES;

                static RRDSET *st_core_throttle_count = NULL;

                if (unlikely(!st_core_throttle_count))
                    st_core_throttle_count = rrdset_create_localhost(
                            "cpu"
                            , "core_throttling"
                            , NULL
                            , "throttling"
                            , "cpu.core_throttling"
                            , "Core Thermal Throttling Events"
                            , "events/s"
                            , "proc"
                            , "stat"
                            , 5001
                            , update_every
                            , RRDSET_TYPE_LINE
                    );
                else
                    rrdset_next(st_core_throttle_count);

                chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, CORE_THROTTLE_COUNT_INDEX, st_core_throttle_count, 1, 1, RRD_ALGORITHM_INCREMENTAL);
                rrdset_done(st_core_throttle_count);
            }
        }

        if(likely(do_package_throttle_count != CONFIG_BOOLEAN_NO)) {
            int r = read_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, PACKAGE_THROTTLE_COUNT_INDEX);
            if(likely(r != -1 && (do_package_throttle_count == CONFIG_BOOLEAN_YES || r > 0))) {
                do_package_throttle_count = CONFIG_BOOLEAN_YES;

                static RRDSET *st_package_throttle_count = NULL;

                if(unlikely(!st_package_throttle_count))
                    st_package_throttle_count = rrdset_create_localhost(
                            "cpu"
                            , "package_throttling"
                            , NULL
                            , "throttling"
                            , "cpu.package_throttling"
                            , "Package Thermal Throttling Events"
                            , "events/s"
                            , "proc"
                            , "stat"
                            , 5002
                            , update_every
                            , RRDSET_TYPE_LINE
                    );
                else
                    rrdset_next(st_package_throttle_count);

                chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, PACKAGE_THROTTLE_COUNT_INDEX, st_package_throttle_count, 1, 1, RRD_ALGORITHM_INCREMENTAL);
                rrdset_done(st_package_throttle_count);
            }
        }

        if(likely(do_scaling_cur_freq != CONFIG_BOOLEAN_NO)) {
            int r = read_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, SCALING_CUR_FREQ_INDEX);
            if(likely(r != -1 && (do_scaling_cur_freq == CONFIG_BOOLEAN_YES || r > 0))) {
                do_scaling_cur_freq = CONFIG_BOOLEAN_YES;

                static RRDSET *st_scaling_cur_freq = NULL;

                if(unlikely(!st_scaling_cur_freq))
                    st_scaling_cur_freq = rrdset_create_localhost(
                            "cpu"
                            , "scaling_cur_freq"
                            , NULL
                            , "cpufreq"
                            , "cpu.scaling_cur_freq"
                            , "Per CPU Core, Current CPU Scaling Frequency"
                            , "MHz"
                            , "proc"
                            , "stat"
                            , 5003
                            , update_every
                            , RRDSET_TYPE_LINE
                    );
                else
                    rrdset_next(st_scaling_cur_freq);

                chart_per_core_files(&all_cpu_charts[1], all_cpu_charts_size - 1, SCALING_CUR_FREQ_INDEX, st_scaling_cur_freq, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
                rrdset_done(st_scaling_cur_freq);
            }
        }
    }

    return 0;
}
コード例 #19
0
int do_proc_sys_devices_system_edac_mc(int update_every, usec_t dt) {
    (void)dt;

    if(unlikely(mc_root == NULL)) {
        find_all_mc();
        if(unlikely(mc_root == NULL))
            return 1;
    }

    static int do_ce = -1, do_ue = -1;
    calculated_number ce_sum = 0, ue_sum = 0;
    struct mc *m;

    if(unlikely(do_ce == -1)) {
        do_ce = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory correctable errors", CONFIG_BOOLEAN_AUTO);
        do_ue = config_get_boolean_ondemand("plugin:proc:/sys/devices/system/edac/mc", "enable ECC memory uncorrectable errors", CONFIG_BOOLEAN_AUTO);
    }

    if(do_ce != CONFIG_BOOLEAN_NO) {
        for(m = mc_root; m; m = m->next) {
            if(m->ce_count_filename) {
                m->ce_updated = 0;

                if(unlikely(!m->ce_ff)) {
                    m->ce_ff = procfile_open(m->ce_count_filename, " \t", PROCFILE_FLAG_DEFAULT);
                    if(unlikely(!m->ce_ff))
                        continue;
                }

                m->ce_ff = procfile_readall(m->ce_ff);
                if(unlikely(!m->ce_ff || procfile_lines(m->ce_ff) < 1 || procfile_linewords(m->ce_ff, 0) < 1))
                    continue;

                m->ce_count = str2ull(procfile_lineword(m->ce_ff, 0, 0));
                ce_sum += m->ce_count;
                m->ce_updated = 1;
            }
        }
    }

    if(do_ue != CONFIG_BOOLEAN_NO) {
        for(m = mc_root; m; m = m->next) {
            if(m->ue_count_filename) {
                m->ue_updated = 0;

                if(unlikely(!m->ue_ff)) {
                    m->ue_ff = procfile_open(m->ue_count_filename, " \t", PROCFILE_FLAG_DEFAULT);
                    if(unlikely(!m->ue_ff))
                        continue;
                }

                m->ue_ff = procfile_readall(m->ue_ff);
                if(unlikely(!m->ue_ff || procfile_lines(m->ue_ff) < 1 || procfile_linewords(m->ue_ff, 0) < 1))
                    continue;

                m->ue_count = str2ull(procfile_lineword(m->ue_ff, 0, 0));
                ue_sum += m->ue_count;
                m->ue_updated = 1;
            }
        }
    }

    // --------------------------------------------------------------------

    if(do_ce == CONFIG_BOOLEAN_YES || (do_ce == CONFIG_BOOLEAN_AUTO && ce_sum > 0)) {
        do_ce = CONFIG_BOOLEAN_YES;

        static RRDSET *ce_st = NULL;

        if(unlikely(!ce_st)) {
            ce_st = rrdset_create_localhost(
                    "mem"
                    , "ecc_ce"
                    , NULL
                    , "ecc"
                    , NULL
                    , "ECC Memory Correctable Errors"
                    , "errors"
                    , "proc"
                    , "/sys/devices/system/edac/mc"
                    , NETDATA_CHART_PRIO_MEM_HW + 50
                    , update_every
                    , RRDSET_TYPE_LINE
            );
        }
        else
            rrdset_next(ce_st);

        for(m = mc_root; m; m = m->next) {
            if (m->ce_count_filename && m->ce_updated) {
                if(unlikely(!m->ce_rd))
                    m->ce_rd = rrddim_add(ce_st, m->name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);

                rrddim_set_by_pointer(ce_st, m->ce_rd, m->ce_count);
            }
        }

        rrdset_done(ce_st);
    }

    // --------------------------------------------------------------------

    if(do_ue == CONFIG_BOOLEAN_YES || (do_ue == CONFIG_BOOLEAN_AUTO && ue_sum > 0)) {
        do_ue = CONFIG_BOOLEAN_YES;

        static RRDSET *ue_st = NULL;

        if(unlikely(!ue_st)) {
            ue_st = rrdset_create_localhost(
                    "mem"
                    , "ecc_ue"
                    , NULL
                    , "ecc"
                    , NULL
                    , "ECC Memory Uncorrectable Errors"
                    , "errors"
                    , "proc"
                    , "/sys/devices/system/edac/mc"
                    , NETDATA_CHART_PRIO_MEM_HW + 60
                    , update_every
                    , RRDSET_TYPE_LINE
            );
        }
        else
            rrdset_next(ue_st);

        for(m = mc_root; m; m = m->next) {
            if (m->ue_count_filename && m->ue_updated) {
                if(unlikely(!m->ue_rd))
                    m->ue_rd = rrddim_add(ue_st, m->name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);

                rrddim_set_by_pointer(ue_st, m->ue_rd, m->ue_count);
            }
        }

        rrdset_done(ue_st);
    }

    return 0;
}
コード例 #20
0
ファイル: proc_net_netstat.c プロジェクト: Brainiarc7/netdata
int do_proc_net_netstat(int update_every, unsigned long long dt) {
	static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1;
	static procfile *ff = NULL;

	if(do_bandwidth == -1)	do_bandwidth	= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
	if(do_inerrors == -1)	do_inerrors		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND);
	if(do_mcast == -1)		do_mcast 		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
	if(do_bcast == -1)		do_bcast 		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
	if(do_mcast_p == -1)	do_mcast_p 		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
	if(do_bcast_p == -1)	do_bcast_p 		= config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND);

	if(dt) {};

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/netstat");
		ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "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;

	for(l = 0; l < lines ;l++) {
		if(strcmp(procfile_lineword(ff, l, 0), "IpExt") == 0) {
			l++; // we need the next line

			if(strcmp(procfile_lineword(ff, l, 0), "IpExt") != 0) {
				error("Cannot read IpExt line from /proc/net/netstat.");
				break;
			}
			words = procfile_linewords(ff, l);
			if(words < 12) {
				error("Cannot read /proc/net/netstat IpExt line. Expected 12 params, read %d.", words);
				continue;
			}

			unsigned long long
				InNoRoutes = 0, InTruncatedPkts = 0,
				InOctets = 0,  InMcastPkts = 0,  InBcastPkts = 0,  InMcastOctets = 0,  InBcastOctets = 0,
				OutOctets = 0, OutMcastPkts = 0, OutBcastPkts = 0, OutMcastOctets = 0, OutBcastOctets = 0;

			InNoRoutes 			= strtoull(procfile_lineword(ff, l, 1), NULL, 10);
			InTruncatedPkts 	= strtoull(procfile_lineword(ff, l, 2), NULL, 10);
			InMcastPkts 		= strtoull(procfile_lineword(ff, l, 3), NULL, 10);
			OutMcastPkts 		= strtoull(procfile_lineword(ff, l, 4), NULL, 10);
			InBcastPkts 		= strtoull(procfile_lineword(ff, l, 5), NULL, 10);
			OutBcastPkts 		= strtoull(procfile_lineword(ff, l, 6), NULL, 10);
			InOctets 			= strtoull(procfile_lineword(ff, l, 7), NULL, 10);
			OutOctets 			= strtoull(procfile_lineword(ff, l, 8), NULL, 10);
			InMcastOctets 		= strtoull(procfile_lineword(ff, l, 9), NULL, 10);
			OutMcastOctets 		= strtoull(procfile_lineword(ff, l, 10), NULL, 10);
			InBcastOctets 		= strtoull(procfile_lineword(ff, l, 11), NULL, 10);
			OutBcastOctets 		= strtoull(procfile_lineword(ff, l, 12), NULL, 10);

			RRDSET *st;

			// --------------------------------------------------------------------

			if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (InOctets || OutOctets))) {
				do_bandwidth = CONFIG_ONDEMAND_YES;
				st = rrdset_find("system.ipv4");
				if(!st) {
					st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, 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, "sent", OutOctets);
				rrddim_set(st, "received", InOctets);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (InNoRoutes || InTruncatedPkts))) {
				do_inerrors = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.inerrors");
				if(!st) {
					st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE);
					st->isdetail = 1;

					rrddim_add(st, "noroutes", NULL, 1, 1, RRDDIM_INCREMENTAL);
					rrddim_add(st, "truncated", NULL, 1, 1, RRDDIM_INCREMENTAL);
				}
				else rrdset_next(st);

				rrddim_set(st, "noroutes", InNoRoutes);
				rrddim_set(st, "truncated", InTruncatedPkts);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (InMcastOctets || OutMcastOctets))) {
				do_mcast = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.mcast");
				if(!st) {
					st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
					st->isdetail = 1;

					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, "sent", OutMcastOctets);
				rrddim_set(st, "received", InMcastOctets);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (InBcastOctets || OutBcastOctets))) {
				do_bcast = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.bcast");
				if(!st) {
					st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
					st->isdetail = 1;

					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, "sent", OutBcastOctets);
				rrddim_set(st, "received", InBcastOctets);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (InMcastPkts || OutMcastPkts))) {
				do_mcast_p = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.mcastpkts");
				if(!st) {
					st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 9500, update_every, RRDSET_TYPE_LINE);
					st->isdetail = 1;

					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, "sent", OutMcastPkts);
				rrddim_set(st, "received", InMcastPkts);
				rrdset_done(st);
			}

			// --------------------------------------------------------------------

			if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (InBcastPkts || OutBcastPkts))) {
				do_bcast_p = CONFIG_ONDEMAND_YES;
				st = rrdset_find("ipv4.bcastpkts");
				if(!st) {
					st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE);
					st->isdetail = 1;

					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, "sent", OutBcastPkts);
				rrddim_set(st, "received", InBcastPkts);
				rrdset_done(st);
			}
		}
	}

	return 0;
}
コード例 #21
0
int do_proc_net_netstat(int update_every, usec_t dt) {
    (void)dt;

    static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1, do_ecn = -1, \
        do_tcpext_reorder = -1, do_tcpext_syscookies = -1, do_tcpext_ofo = -1, do_tcpext_connaborts = -1, do_tcpext_memory = -1;
    static uint32_t hash_ipext = 0, hash_tcpext = 0;
    static procfile *ff = NULL;

    static unsigned long long *tcpext_TCPRenoReorder = NULL;
    static unsigned long long *tcpext_TCPFACKReorder = NULL;
    static unsigned long long *tcpext_TCPSACKReorder = NULL;
    static unsigned long long *tcpext_TCPTSReorder = NULL;

    static unsigned long long *tcpext_SyncookiesSent = NULL;
    static unsigned long long *tcpext_SyncookiesRecv = NULL;
    static unsigned long long *tcpext_SyncookiesFailed = NULL;

    static unsigned long long *tcpext_TCPOFOQueue = NULL; // Number of packets queued in OFO queue
    static unsigned long long *tcpext_TCPOFODrop = NULL;  // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
    static unsigned long long *tcpext_TCPOFOMerge = NULL; // Number of packets in OFO that were merged with other packets.
    static unsigned long long *tcpext_OfoPruned = NULL;   // packets dropped from out-of-order queue because of socket buffer overrun

    static unsigned long long *tcpext_TCPAbortOnData = NULL;    // connections reset due to unexpected data
    static unsigned long long *tcpext_TCPAbortOnClose = NULL;   // connections reset due to early user close
    static unsigned long long *tcpext_TCPAbortOnMemory = NULL;  // connections aborted due to memory pressure
    static unsigned long long *tcpext_TCPAbortOnTimeout = NULL; // connections aborted due to timeout
    static unsigned long long *tcpext_TCPAbortOnLinger = NULL;  // connections aborted after user close in linger timeout
    static unsigned long long *tcpext_TCPAbortFailed = NULL;    // times unable to send RST due to no memory

    static unsigned long long *tcpext_TCPMemoryPressures = NULL;

/*
    // connection rejects
    static unsigned long long *tcpext_PAWSActive = NULL;  // active connections rejected because of time stamp
    static unsigned long long *tcpext_PAWSPassive = NULL; // passive connections rejected because of time stamp

    static unsigned long long *tcpext_TCPTimeouts = NULL;

    static unsigned long long *tcpext_TCPDSACKUndo = NULL;
    static unsigned long long *tcpext_TCPDSACKOldSent = NULL;
    static unsigned long long *tcpext_TCPDSACKOfoSent = NULL;
    static unsigned long long *tcpext_TCPDSACKRecv = NULL;
    static unsigned long long *tcpext_TCPDSACKOfoRecv = NULL;
    static unsigned long long *tcpext_TCPDSACKIgnoredOld = NULL;
    static unsigned long long *tcpext_TCPDSACKIgnoredNoUndo = NULL;


    static unsigned long long *tcpext_EmbryonicRsts = NULL;

    static unsigned long long *tcpext_PruneCalled = NULL;
    static unsigned long long *tcpext_RcvPruned = NULL;
    static unsigned long long *tcpext_OutOfWindowIcmps = NULL;
    static unsigned long long *tcpext_LockDroppedIcmps = NULL;
    static unsigned long long *tcpext_ArpFilter = NULL;

    static unsigned long long *tcpext_TW = NULL;
    static unsigned long long *tcpext_TWRecycled = NULL;
    static unsigned long long *tcpext_TWKilled = NULL;

    static unsigned long long *tcpext_PAWSEstab = NULL;

    static unsigned long long *tcpext_DelayedACKs = NULL;
    static unsigned long long *tcpext_DelayedACKLocked = NULL;
    static unsigned long long *tcpext_DelayedACKLost = NULL;

    static unsigned long long *tcpext_ListenOverflows = NULL;
    static unsigned long long *tcpext_ListenDrops = NULL;

    static unsigned long long *tcpext_TCPPrequeued = NULL;

    static unsigned long long *tcpext_TCPDirectCopyFromBacklog = NULL;
    static unsigned long long *tcpext_TCPDirectCopyFromPrequeue = NULL;
    static unsigned long long *tcpext_TCPPrequeueDropped = NULL;

    static unsigned long long *tcpext_TCPHPHits = NULL;
    static unsigned long long *tcpext_TCPHPHitsToUser = NULL;
    static unsigned long long *tcpext_TCPHPAcks = NULL;

    static unsigned long long *tcpext_TCPPureAcks = NULL;
    static unsigned long long *tcpext_TCPRenoRecovery = NULL;

    static unsigned long long *tcpext_TCPSackRecovery = NULL;
    static unsigned long long *tcpext_TCPSackFailures = NULL;
    static unsigned long long *tcpext_TCPSACKReneging = NULL;
    static unsigned long long *tcpext_TCPSackRecoveryFail = NULL;
    static unsigned long long *tcpext_TCPSACKDiscard = NULL;
    static unsigned long long *tcpext_TCPSackShifted = NULL;
    static unsigned long long *tcpext_TCPSackMerged = NULL;
    static unsigned long long *tcpext_TCPSackShiftFallback = NULL;


    static unsigned long long *tcpext_TCPFullUndo = NULL;
    static unsigned long long *tcpext_TCPPartialUndo = NULL;

    static unsigned long long *tcpext_TCPLossUndo = NULL;
    static unsigned long long *tcpext_TCPLostRetransmit = NULL;

    static unsigned long long *tcpext_TCPRenoFailures = NULL;

    static unsigned long long *tcpext_TCPLossFailures = NULL;
    static unsigned long long *tcpext_TCPFastRetrans = NULL;
    static unsigned long long *tcpext_TCPForwardRetrans = NULL;
    static unsigned long long *tcpext_TCPSlowStartRetrans = NULL;
    static unsigned long long *tcpext_TCPLossProbes = NULL;
    static unsigned long long *tcpext_TCPLossProbeRecovery = NULL;
    static unsigned long long *tcpext_TCPRenoRecoveryFail = NULL;
    static unsigned long long *tcpext_TCPSchedulerFailed = NULL;
    static unsigned long long *tcpext_TCPRcvCollapsed = NULL;

    static unsigned long long *tcpext_TCPSpuriousRTOs = NULL;
    static unsigned long long *tcpext_TCPMD5NotFound = NULL;
    static unsigned long long *tcpext_TCPMD5Unexpected = NULL;

    static unsigned long long *tcpext_TCPBacklogDrop = NULL;
    static unsigned long long *tcpext_TCPMinTTLDrop = NULL;
    static unsigned long long *tcpext_TCPDeferAcceptDrop = NULL;
    static unsigned long long *tcpext_IPReversePathFilter = NULL;
    static unsigned long long *tcpext_TCPTimeWaitOverflow = NULL;
    static unsigned long long *tcpext_TCPReqQFullDoCookies = NULL;
    static unsigned long long *tcpext_TCPReqQFullDrop = NULL;
    static unsigned long long *tcpext_TCPRetransFail = NULL;
    static unsigned long long *tcpext_TCPRcvCoalesce = NULL;

    static unsigned long long *tcpext_TCPChallengeACK = NULL;
    static unsigned long long *tcpext_TCPSYNChallenge = NULL;

    static unsigned long long *tcpext_TCPFastOpenActive = NULL;
    static unsigned long long *tcpext_TCPFastOpenActiveFail = NULL;
    static unsigned long long *tcpext_TCPFastOpenPassive = NULL;
    static unsigned long long *tcpext_TCPFastOpenPassiveFail = NULL;
    static unsigned long long *tcpext_TCPFastOpenListenOverflow = NULL;
    static unsigned long long *tcpext_TCPFastOpenCookieReqd = NULL;

    static unsigned long long *tcpext_TCPSpuriousRtxHostQueues = NULL;
    static unsigned long long *tcpext_BusyPollRxPackets = NULL;
    static unsigned long long *tcpext_TCPAutoCorking = NULL;
    static unsigned long long *tcpext_TCPFromZeroWindowAdv = NULL;
    static unsigned long long *tcpext_TCPToZeroWindowAdv = NULL;
    static unsigned long long *tcpext_TCPWantZeroWindowAdv = NULL;
    static unsigned long long *tcpext_TCPSynRetrans = NULL;
    static unsigned long long *tcpext_TCPOrigDataSent = NULL;

    static unsigned long long *tcpext_TCPHystartTrainDetect = NULL;
    static unsigned long long *tcpext_TCPHystartTrainCwnd = NULL;
    static unsigned long long *tcpext_TCPHystartDelayDetect = NULL;
    static unsigned long long *tcpext_TCPHystartDelayCwnd = NULL;

    static unsigned long long *tcpext_TCPACKSkippedSynRecv = NULL;
    static unsigned long long *tcpext_TCPACKSkippedPAWS = NULL;
    static unsigned long long *tcpext_TCPACKSkippedSeq = NULL;
    static unsigned long long *tcpext_TCPACKSkippedFinWait2 = NULL;
    static unsigned long long *tcpext_TCPACKSkippedTimeWait = NULL;
    static unsigned long long *tcpext_TCPACKSkippedChallenge = NULL;

    static unsigned long long *tcpext_TCPWinProbe = NULL;
    static unsigned long long *tcpext_TCPKeepAlive = NULL;

    static unsigned long long *tcpext_TCPMTUPFail = NULL;
    static unsigned long long *tcpext_TCPMTUPSuccess = NULL;
*/

    static unsigned long long *ipext_InNoRoutes = NULL;
    static unsigned long long *ipext_InTruncatedPkts = NULL;
    static unsigned long long *ipext_InMcastPkts = NULL;
    static unsigned long long *ipext_OutMcastPkts = NULL;
    static unsigned long long *ipext_InBcastPkts = NULL;
    static unsigned long long *ipext_OutBcastPkts = NULL;
    static unsigned long long *ipext_InOctets = NULL;
    static unsigned long long *ipext_OutOctets = NULL;
    static unsigned long long *ipext_InMcastOctets = NULL;
    static unsigned long long *ipext_OutMcastOctets = NULL;
    static unsigned long long *ipext_InBcastOctets = NULL;
    static unsigned long long *ipext_OutBcastOctets = NULL;
    static unsigned long long *ipext_InCsumErrors = NULL;
    static unsigned long long *ipext_InNoECTPkts = NULL;
    static unsigned long long *ipext_InECT1Pkts = NULL;
    static unsigned long long *ipext_InECT0Pkts = NULL;
    static unsigned long long *ipext_InCEPkts = NULL;

    if(unlikely(do_bandwidth == -1)) {
        do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_inerrors  = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "input errors", CONFIG_ONDEMAND_ONDEMAND);
        do_mcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_bcast     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast bandwidth", CONFIG_ONDEMAND_ONDEMAND);
        do_mcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "multicast packets", CONFIG_ONDEMAND_ONDEMAND);
        do_bcast_p   = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "broadcast packets", CONFIG_ONDEMAND_ONDEMAND);
        do_ecn       = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "ECN packets", CONFIG_ONDEMAND_ONDEMAND);

        do_tcpext_reorder    = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP reorders", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_syscookies = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP SYN cookies", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_ofo        = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP out-of-order queue", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_connaborts = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP connection aborts", CONFIG_ONDEMAND_ONDEMAND);
        do_tcpext_memory     = config_get_boolean_ondemand("plugin:proc:/proc/net/netstat", "TCP memory pressures", CONFIG_ONDEMAND_ONDEMAND);

        hash_ipext = simple_hash("IpExt");
        hash_tcpext = simple_hash("TcpExt");

        hash_array(ipext_data);
        hash_array(tcpext_data);

        // Reordering
        tcpext_TCPFACKReorder = netstat_columns_find(tcpext_data, "TCPFACKReorder");
        tcpext_TCPSACKReorder = netstat_columns_find(tcpext_data, "TCPSACKReorder");
        tcpext_TCPRenoReorder = netstat_columns_find(tcpext_data, "TCPRenoReorder");
        tcpext_TCPTSReorder = netstat_columns_find(tcpext_data, "TCPTSReorder");

        // SYN Cookies
        tcpext_SyncookiesSent = netstat_columns_find(tcpext_data, "SyncookiesSent");
        tcpext_SyncookiesRecv = netstat_columns_find(tcpext_data, "SyncookiesRecv");
        tcpext_SyncookiesFailed = netstat_columns_find(tcpext_data, "SyncookiesFailed");

        // Out Of Order Queue
        // http://www.spinics.net/lists/netdev/msg204696.html
        tcpext_TCPOFOQueue = netstat_columns_find(tcpext_data, "TCPOFOQueue"); // Number of packets queued in OFO queue
        tcpext_TCPOFODrop  = netstat_columns_find(tcpext_data, "TCPOFODrop");  // Number of packets meant to be queued in OFO but dropped because socket rcvbuf limit hit.
        tcpext_TCPOFOMerge = netstat_columns_find(tcpext_data, "TCPOFOMerge"); // Number of packets in OFO that were merged with other packets.
        tcpext_OfoPruned   = netstat_columns_find(tcpext_data, "OfoPruned");   // packets dropped from out-of-order queue because of socket buffer overrun

        // connection resets
        // https://github.com/ecki/net-tools/blob/bd8bceaed2311651710331a7f8990c3e31be9840/statistics.c
        tcpext_TCPAbortOnData    = netstat_columns_find(tcpext_data, "TCPAbortOnData");    // connections reset due to unexpected data
        tcpext_TCPAbortOnClose   = netstat_columns_find(tcpext_data, "TCPAbortOnClose");   // connections reset due to early user close
        tcpext_TCPAbortOnMemory  = netstat_columns_find(tcpext_data, "TCPAbortOnMemory");  // connections aborted due to memory pressure
        tcpext_TCPAbortOnTimeout = netstat_columns_find(tcpext_data, "TCPAbortOnTimeout"); // connections aborted due to timeout
        tcpext_TCPAbortOnLinger  = netstat_columns_find(tcpext_data, "TCPAbortOnLinger");  // connections aborted after user close in linger timeout
        tcpext_TCPAbortFailed    = netstat_columns_find(tcpext_data, "TCPAbortFailed");    // times unable to send RST due to no memory

        tcpext_TCPMemoryPressures = netstat_columns_find(tcpext_data, "TCPMemoryPressures");

        /*
        tcpext_EmbryonicRsts = netstat_columns_find(tcpext_data, "EmbryonicRsts");
        tcpext_PruneCalled = netstat_columns_find(tcpext_data, "PruneCalled");
        tcpext_RcvPruned = netstat_columns_find(tcpext_data, "RcvPruned");
        tcpext_OutOfWindowIcmps = netstat_columns_find(tcpext_data, "OutOfWindowIcmps");
        tcpext_LockDroppedIcmps = netstat_columns_find(tcpext_data, "LockDroppedIcmps");
        tcpext_ArpFilter = netstat_columns_find(tcpext_data, "ArpFilter");
        tcpext_TW = netstat_columns_find(tcpext_data, "TW");
        tcpext_TWRecycled = netstat_columns_find(tcpext_data, "TWRecycled");
        tcpext_TWKilled = netstat_columns_find(tcpext_data, "TWKilled");
        tcpext_PAWSPassive = netstat_columns_find(tcpext_data, "PAWSPassive");
        tcpext_PAWSActive = netstat_columns_find(tcpext_data, "PAWSActive");
        tcpext_PAWSEstab = netstat_columns_find(tcpext_data, "PAWSEstab");
        tcpext_DelayedACKs = netstat_columns_find(tcpext_data, "DelayedACKs");
        tcpext_DelayedACKLocked = netstat_columns_find(tcpext_data, "DelayedACKLocked");
        tcpext_DelayedACKLost = netstat_columns_find(tcpext_data, "DelayedACKLost");
        tcpext_ListenOverflows = netstat_columns_find(tcpext_data, "ListenOverflows");
        tcpext_ListenDrops = netstat_columns_find(tcpext_data, "ListenDrops");
        tcpext_TCPPrequeued = netstat_columns_find(tcpext_data, "TCPPrequeued");
        tcpext_TCPDirectCopyFromBacklog = netstat_columns_find(tcpext_data, "TCPDirectCopyFromBacklog");
        tcpext_TCPDirectCopyFromPrequeue = netstat_columns_find(tcpext_data, "TCPDirectCopyFromPrequeue");
        tcpext_TCPPrequeueDropped = netstat_columns_find(tcpext_data, "TCPPrequeueDropped");
        tcpext_TCPHPHits = netstat_columns_find(tcpext_data, "TCPHPHits");
        tcpext_TCPHPHitsToUser = netstat_columns_find(tcpext_data, "TCPHPHitsToUser");
        tcpext_TCPPureAcks = netstat_columns_find(tcpext_data, "TCPPureAcks");
        tcpext_TCPHPAcks = netstat_columns_find(tcpext_data, "TCPHPAcks");
        tcpext_TCPRenoRecovery = netstat_columns_find(tcpext_data, "TCPRenoRecovery");
        tcpext_TCPSackRecovery = netstat_columns_find(tcpext_data, "TCPSackRecovery");
        tcpext_TCPSACKReneging = netstat_columns_find(tcpext_data, "TCPSACKReneging");
        tcpext_TCPFullUndo = netstat_columns_find(tcpext_data, "TCPFullUndo");
        tcpext_TCPPartialUndo = netstat_columns_find(tcpext_data, "TCPPartialUndo");
        tcpext_TCPDSACKUndo = netstat_columns_find(tcpext_data, "TCPDSACKUndo");
        tcpext_TCPLossUndo = netstat_columns_find(tcpext_data, "TCPLossUndo");
        tcpext_TCPLostRetransmit = netstat_columns_find(tcpext_data, "TCPLostRetransmit");
        tcpext_TCPRenoFailures = netstat_columns_find(tcpext_data, "TCPRenoFailures");
        tcpext_TCPSackFailures = netstat_columns_find(tcpext_data, "TCPSackFailures");
        tcpext_TCPLossFailures = netstat_columns_find(tcpext_data, "TCPLossFailures");
        tcpext_TCPFastRetrans = netstat_columns_find(tcpext_data, "TCPFastRetrans");
        tcpext_TCPForwardRetrans = netstat_columns_find(tcpext_data, "TCPForwardRetrans");
        tcpext_TCPSlowStartRetrans = netstat_columns_find(tcpext_data, "TCPSlowStartRetrans");
        tcpext_TCPTimeouts = netstat_columns_find(tcpext_data, "TCPTimeouts");
        tcpext_TCPLossProbes = netstat_columns_find(tcpext_data, "TCPLossProbes");
        tcpext_TCPLossProbeRecovery = netstat_columns_find(tcpext_data, "TCPLossProbeRecovery");
        tcpext_TCPRenoRecoveryFail = netstat_columns_find(tcpext_data, "TCPRenoRecoveryFail");
        tcpext_TCPSackRecoveryFail = netstat_columns_find(tcpext_data, "TCPSackRecoveryFail");
        tcpext_TCPSchedulerFailed = netstat_columns_find(tcpext_data, "TCPSchedulerFailed");
        tcpext_TCPRcvCollapsed = netstat_columns_find(tcpext_data, "TCPRcvCollapsed");
        tcpext_TCPDSACKOldSent = netstat_columns_find(tcpext_data, "TCPDSACKOldSent");
        tcpext_TCPDSACKOfoSent = netstat_columns_find(tcpext_data, "TCPDSACKOfoSent");
        tcpext_TCPDSACKRecv = netstat_columns_find(tcpext_data, "TCPDSACKRecv");
        tcpext_TCPDSACKOfoRecv = netstat_columns_find(tcpext_data, "TCPDSACKOfoRecv");
        tcpext_TCPSACKDiscard = netstat_columns_find(tcpext_data, "TCPSACKDiscard");
        tcpext_TCPDSACKIgnoredOld = netstat_columns_find(tcpext_data, "TCPDSACKIgnoredOld");
        tcpext_TCPDSACKIgnoredNoUndo = netstat_columns_find(tcpext_data, "TCPDSACKIgnoredNoUndo");
        tcpext_TCPSpuriousRTOs = netstat_columns_find(tcpext_data, "TCPSpuriousRTOs");
        tcpext_TCPMD5NotFound = netstat_columns_find(tcpext_data, "TCPMD5NotFound");
        tcpext_TCPMD5Unexpected = netstat_columns_find(tcpext_data, "TCPMD5Unexpected");
        tcpext_TCPSackShifted = netstat_columns_find(tcpext_data, "TCPSackShifted");
        tcpext_TCPSackMerged = netstat_columns_find(tcpext_data, "TCPSackMerged");
        tcpext_TCPSackShiftFallback = netstat_columns_find(tcpext_data, "TCPSackShiftFallback");
        tcpext_TCPBacklogDrop = netstat_columns_find(tcpext_data, "TCPBacklogDrop");
        tcpext_TCPMinTTLDrop = netstat_columns_find(tcpext_data, "TCPMinTTLDrop");
        tcpext_TCPDeferAcceptDrop = netstat_columns_find(tcpext_data, "TCPDeferAcceptDrop");
        tcpext_IPReversePathFilter = netstat_columns_find(tcpext_data, "IPReversePathFilter");
        tcpext_TCPTimeWaitOverflow = netstat_columns_find(tcpext_data, "TCPTimeWaitOverflow");
        tcpext_TCPReqQFullDoCookies = netstat_columns_find(tcpext_data, "TCPReqQFullDoCookies");
        tcpext_TCPReqQFullDrop = netstat_columns_find(tcpext_data, "TCPReqQFullDrop");
        tcpext_TCPRetransFail = netstat_columns_find(tcpext_data, "TCPRetransFail");
        tcpext_TCPRcvCoalesce = netstat_columns_find(tcpext_data, "TCPRcvCoalesce");
        tcpext_TCPChallengeACK = netstat_columns_find(tcpext_data, "TCPChallengeACK");
        tcpext_TCPSYNChallenge = netstat_columns_find(tcpext_data, "TCPSYNChallenge");
        tcpext_TCPFastOpenActive = netstat_columns_find(tcpext_data, "TCPFastOpenActive");
        tcpext_TCPFastOpenActiveFail = netstat_columns_find(tcpext_data, "TCPFastOpenActiveFail");
        tcpext_TCPFastOpenPassive = netstat_columns_find(tcpext_data, "TCPFastOpenPassive");
        tcpext_TCPFastOpenPassiveFail = netstat_columns_find(tcpext_data, "TCPFastOpenPassiveFail");
        tcpext_TCPFastOpenListenOverflow = netstat_columns_find(tcpext_data, "TCPFastOpenListenOverflow");
        tcpext_TCPFastOpenCookieReqd = netstat_columns_find(tcpext_data, "TCPFastOpenCookieReqd");
        tcpext_TCPSpuriousRtxHostQueues = netstat_columns_find(tcpext_data, "TCPSpuriousRtxHostQueues");
        tcpext_BusyPollRxPackets = netstat_columns_find(tcpext_data, "BusyPollRxPackets");
        tcpext_TCPAutoCorking = netstat_columns_find(tcpext_data, "TCPAutoCorking");
        tcpext_TCPFromZeroWindowAdv = netstat_columns_find(tcpext_data, "TCPFromZeroWindowAdv");
        tcpext_TCPToZeroWindowAdv = netstat_columns_find(tcpext_data, "TCPToZeroWindowAdv");
        tcpext_TCPWantZeroWindowAdv = netstat_columns_find(tcpext_data, "TCPWantZeroWindowAdv");
        tcpext_TCPSynRetrans = netstat_columns_find(tcpext_data, "TCPSynRetrans");
        tcpext_TCPOrigDataSent = netstat_columns_find(tcpext_data, "TCPOrigDataSent");
        tcpext_TCPHystartTrainDetect = netstat_columns_find(tcpext_data, "TCPHystartTrainDetect");
        tcpext_TCPHystartTrainCwnd = netstat_columns_find(tcpext_data, "TCPHystartTrainCwnd");
        tcpext_TCPHystartDelayDetect = netstat_columns_find(tcpext_data, "TCPHystartDelayDetect");
        tcpext_TCPHystartDelayCwnd = netstat_columns_find(tcpext_data, "TCPHystartDelayCwnd");
        tcpext_TCPACKSkippedSynRecv = netstat_columns_find(tcpext_data, "TCPACKSkippedSynRecv");
        tcpext_TCPACKSkippedPAWS = netstat_columns_find(tcpext_data, "TCPACKSkippedPAWS");
        tcpext_TCPACKSkippedSeq = netstat_columns_find(tcpext_data, "TCPACKSkippedSeq");
        tcpext_TCPACKSkippedFinWait2 = netstat_columns_find(tcpext_data, "TCPACKSkippedFinWait2");
        tcpext_TCPACKSkippedTimeWait = netstat_columns_find(tcpext_data, "TCPACKSkippedTimeWait");
        tcpext_TCPACKSkippedChallenge = netstat_columns_find(tcpext_data, "TCPACKSkippedChallenge");
        tcpext_TCPWinProbe = netstat_columns_find(tcpext_data, "TCPWinProbe");
        tcpext_TCPKeepAlive = netstat_columns_find(tcpext_data, "TCPKeepAlive");
        tcpext_TCPMTUPFail = netstat_columns_find(tcpext_data, "TCPMTUPFail");
        tcpext_TCPMTUPSuccess = netstat_columns_find(tcpext_data, "TCPMTUPSuccess");
*/
        ipext_InNoRoutes = netstat_columns_find(ipext_data, "InNoRoutes");
        ipext_InTruncatedPkts = netstat_columns_find(ipext_data, "InTruncatedPkts");
        ipext_InMcastPkts = netstat_columns_find(ipext_data, "InMcastPkts");
        ipext_OutMcastPkts = netstat_columns_find(ipext_data, "OutMcastPkts");
        ipext_InBcastPkts = netstat_columns_find(ipext_data, "InBcastPkts");
        ipext_OutBcastPkts = netstat_columns_find(ipext_data, "OutBcastPkts");
        ipext_InOctets = netstat_columns_find(ipext_data, "InOctets");
        ipext_OutOctets = netstat_columns_find(ipext_data, "OutOctets");
        ipext_InMcastOctets = netstat_columns_find(ipext_data, "InMcastOctets");
        ipext_OutMcastOctets = netstat_columns_find(ipext_data, "OutMcastOctets");
        ipext_InBcastOctets = netstat_columns_find(ipext_data, "InBcastOctets");
        ipext_OutBcastOctets = netstat_columns_find(ipext_data, "OutBcastOctets");
        ipext_InCsumErrors = netstat_columns_find(ipext_data, "InCsumErrors");
        ipext_InNoECTPkts = netstat_columns_find(ipext_data, "InNoECTPkts");
        ipext_InECT1Pkts = netstat_columns_find(ipext_data, "InECT1Pkts");
        ipext_InECT0Pkts = netstat_columns_find(ipext_data, "InECT0Pkts");
        ipext_InCEPkts = netstat_columns_find(ipext_data, "InCEPkts");
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/netstat");
        ff = procfile_open(config_get("plugin:proc:/proc/net/netstat", "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;

    for(l = 0; l < lines ;l++) {
        char *key = procfile_lineword(ff, l, 0);
        uint32_t hash = simple_hash(key);

        if(unlikely(hash == hash_ipext && strcmp(key, "IpExt") == 0)) {
            uint32_t h = l++;

            if(unlikely(strcmp(procfile_lineword(ff, l, 0), "IpExt") != 0)) {
                error("Cannot read IpExt line from /proc/net/netstat.");
                break;
            }
            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat IpExt line. Expected 2+ params, read %u.", words);
                continue;
            }

            parse_line_pair(ff, ipext_data, h, l);

            RRDSET *st;

            // --------------------------------------------------------------------

            if(do_bandwidth == CONFIG_ONDEMAND_YES || (do_bandwidth == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InOctets || *ipext_OutOctets))) {
                do_bandwidth = CONFIG_ONDEMAND_YES;
                st = rrdset_find("system.ipv4");
                if(unlikely(!st)) {
                    st = rrdset_create("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", 500, update_every, RRDSET_TYPE_AREA);

                    rrddim_add(st, "InOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InOctets", *ipext_InOctets);
                rrddim_set(st, "OutOctets", *ipext_OutOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_inerrors == CONFIG_ONDEMAND_YES || (do_inerrors == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InNoRoutes || *ipext_InTruncatedPkts))) {
                do_inerrors = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.inerrors");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "inerrors", NULL, "errors", NULL, "IPv4 Input Errors", "packets/s", 4000, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InNoRoutes", "noroutes", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InTruncatedPkts", "truncated", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InCsumErrors", "checksum", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InNoRoutes", *ipext_InNoRoutes);
                rrddim_set(st, "InTruncatedPkts", *ipext_InTruncatedPkts);
                rrddim_set(st, "InCsumErrors", *ipext_InCsumErrors);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_mcast == CONFIG_ONDEMAND_YES || (do_mcast == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InMcastOctets || *ipext_OutMcastOctets))) {
                do_mcast = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.mcast");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "mcast", NULL, "multicast", NULL, "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, RRDSET_TYPE_AREA);
                    st->isdetail = 1;

                    rrddim_add(st, "InMcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutMcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InMcastOctets", *ipext_InMcastOctets);
                rrddim_set(st, "OutMcastOctets", *ipext_OutMcastOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_bcast == CONFIG_ONDEMAND_YES || (do_bcast == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InBcastOctets || *ipext_OutBcastOctets))) {
                do_bcast = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.bcast");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "bcast", NULL, "broadcast", NULL, "IPv4 Broadcast Bandwidth", "kilobits/s", 8000, update_every, RRDSET_TYPE_AREA);
                    st->isdetail = 1;

                    rrddim_add(st, "InBcastOctets", "received", 8, 1024, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutBcastOctets", "sent", -8, 1024, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InBcastOctets", *ipext_InBcastOctets);
                rrddim_set(st, "OutBcastOctets", *ipext_OutBcastOctets);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_mcast_p == CONFIG_ONDEMAND_YES || (do_mcast_p == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InMcastPkts || *ipext_OutMcastPkts))) {
                do_mcast_p = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.mcastpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "mcastpkts", NULL, "multicast", NULL, "IPv4 Multicast Packets", "packets/s", 8600, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InMcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutMcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InMcastPkts", *ipext_InMcastPkts);
                rrddim_set(st, "OutMcastPkts", *ipext_OutMcastPkts);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_bcast_p == CONFIG_ONDEMAND_YES || (do_bcast_p == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InBcastPkts || *ipext_OutBcastPkts))) {
                do_bcast_p = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.bcastpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "bcastpkts", NULL, "broadcast", NULL, "IPv4 Broadcast Packets", "packets/s", 8500, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InBcastPkts", "received", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OutBcastPkts", "sent", -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InBcastPkts", *ipext_InBcastPkts);
                rrddim_set(st, "OutBcastPkts", *ipext_OutBcastPkts);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_ecn == CONFIG_ONDEMAND_YES || (do_ecn == CONFIG_ONDEMAND_ONDEMAND && (*ipext_InCEPkts || *ipext_InECT0Pkts || *ipext_InECT1Pkts || *ipext_InNoECTPkts))) {
                do_ecn = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.ecnpkts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "ecnpkts", NULL, "ecn", NULL, "IPv4 ECN Statistics", "packets/s", 8700, update_every, RRDSET_TYPE_LINE);
                    st->isdetail = 1;

                    rrddim_add(st, "InCEPkts", "CEP", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InNoECTPkts", "NoECTP", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InECT0Pkts", "ECTP0", 1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "InECT1Pkts", "ECTP1", 1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "InCEPkts", *ipext_InCEPkts);
                rrddim_set(st, "InNoECTPkts", *ipext_InNoECTPkts);
                rrddim_set(st, "InECT0Pkts", *ipext_InECT0Pkts);
                rrddim_set(st, "InECT1Pkts", *ipext_InECT1Pkts);
                rrdset_done(st);
            }
        }
        else if(unlikely(hash == hash_tcpext && strcmp(key, "TcpExt") == 0)) {
            uint32_t h = l++;

            if(unlikely(strcmp(procfile_lineword(ff, l, 0), "TcpExt") != 0)) {
                error("Cannot read TcpExt line from /proc/net/netstat.");
                break;
            }
            words = procfile_linewords(ff, l);
            if(unlikely(words < 2)) {
                error("Cannot read /proc/net/netstat TcpExt line. Expected 2+ params, read %u.", words);
                continue;
            }

            parse_line_pair(ff, tcpext_data, h, l);

            RRDSET *st;

            // --------------------------------------------------------------------

            if(do_tcpext_memory == CONFIG_ONDEMAND_YES || (do_tcpext_memory == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPMemoryPressures))) {
                do_tcpext_memory = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpmemorypressures");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpmemorypressures", NULL, "tcp", NULL, "TCP Memory Pressures", "events/s", 3000, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPMemoryPressures",   "pressures",  1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPMemoryPressures", *tcpext_TCPMemoryPressures);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_connaborts == CONFIG_ONDEMAND_YES || (do_tcpext_connaborts == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPAbortOnData || *tcpext_TCPAbortOnClose || *tcpext_TCPAbortOnMemory || *tcpext_TCPAbortOnTimeout || *tcpext_TCPAbortOnLinger || *tcpext_TCPAbortFailed))) {
                do_tcpext_connaborts = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpconnaborts");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpconnaborts", NULL, "tcp", NULL, "TCP Connection Aborts", "connections/s", 3010, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPAbortOnData",    "baddata",     1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnClose",   "userclosed",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnMemory",  "nomemory",    1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnTimeout", "timeout",     1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortOnLinger",  "linger",      1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPAbortFailed",    "failed",     -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPAbortOnData",    *tcpext_TCPAbortOnData);
                rrddim_set(st, "TCPAbortOnClose",   *tcpext_TCPAbortOnClose);
                rrddim_set(st, "TCPAbortOnMemory",  *tcpext_TCPAbortOnMemory);
                rrddim_set(st, "TCPAbortOnTimeout", *tcpext_TCPAbortOnTimeout);
                rrddim_set(st, "TCPAbortOnLinger",  *tcpext_TCPAbortOnLinger);
                rrddim_set(st, "TCPAbortFailed",    *tcpext_TCPAbortFailed);
                rrdset_done(st);
            }
            // --------------------------------------------------------------------

            if(do_tcpext_reorder == CONFIG_ONDEMAND_YES || (do_tcpext_reorder == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPRenoReorder || *tcpext_TCPFACKReorder || *tcpext_TCPSACKReorder || *tcpext_TCPTSReorder))) {
                do_tcpext_reorder = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpreorders");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpreorders", NULL, "tcp", NULL, "TCP Reordered Packets by Detection Method", "packets/s", 3020, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPTSReorder",   "timestamp",   1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPSACKReorder", "sack",        1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPFACKReorder", "fack",        1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPRenoReorder", "reno",        1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPTSReorder",   *tcpext_TCPTSReorder);
                rrddim_set(st, "TCPSACKReorder", *tcpext_TCPSACKReorder);
                rrddim_set(st, "TCPFACKReorder", *tcpext_TCPFACKReorder);
                rrddim_set(st, "TCPRenoReorder", *tcpext_TCPRenoReorder);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_ofo == CONFIG_ONDEMAND_YES || (do_tcpext_ofo == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_TCPOFOQueue || *tcpext_TCPOFODrop || *tcpext_TCPOFOMerge))) {
                do_tcpext_ofo = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpofo");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpofo", NULL, "tcp", NULL, "TCP Out-Of-Order Queue", "packets/s", 3050, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "TCPOFOQueue", "inqueue",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPOFODrop",  "dropped", -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "TCPOFOMerge", "merged",   1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "OfoPruned",   "pruned",  -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "TCPOFOQueue",   *tcpext_TCPOFOQueue);
                rrddim_set(st, "TCPOFODrop",    *tcpext_TCPOFODrop);
                rrddim_set(st, "TCPOFOMerge",   *tcpext_TCPOFOMerge);
                rrddim_set(st, "OfoPruned",     *tcpext_OfoPruned);
                rrdset_done(st);
            }

            // --------------------------------------------------------------------

            if(do_tcpext_syscookies == CONFIG_ONDEMAND_YES || (do_tcpext_syscookies == CONFIG_ONDEMAND_ONDEMAND && (*tcpext_SyncookiesSent || *tcpext_SyncookiesRecv || *tcpext_SyncookiesFailed))) {
                do_tcpext_syscookies = CONFIG_ONDEMAND_YES;
                st = rrdset_find("ipv4.tcpsyncookies");
                if(unlikely(!st)) {
                    st = rrdset_create("ipv4", "tcpsyncookies", NULL, "tcp", NULL, "TCP SYN Cookies", "packets/s", 3100, update_every, RRDSET_TYPE_LINE);

                    rrddim_add(st, "SyncookiesRecv",   "received",  1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SyncookiesSent",   "sent",     -1, 1, RRDDIM_INCREMENTAL);
                    rrddim_add(st, "SyncookiesFailed", "failed",   -1, 1, RRDDIM_INCREMENTAL);
                }
                else rrdset_next(st);

                rrddim_set(st, "SyncookiesRecv",   *tcpext_SyncookiesRecv);
                rrddim_set(st, "SyncookiesSent",   *tcpext_SyncookiesSent);
                rrddim_set(st, "SyncookiesFailed", *tcpext_SyncookiesFailed);
                rrdset_done(st);
            }

        }
    }

    return 0;
}
コード例 #22
0
int do_proc_net_stat_synproxy(int update_every, unsigned long long dt) {
    (void)dt;

    static int do_entries = -1, do_cookies = -1, do_syns = -1, do_reopened = -1;
    static procfile *ff = NULL;

    if(unlikely(do_entries == -1)) {
        do_entries  = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY entries", CONFIG_ONDEMAND_ONDEMAND);
        do_cookies  = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY cookies", CONFIG_ONDEMAND_ONDEMAND);
        do_syns     = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY SYN received", CONFIG_ONDEMAND_ONDEMAND);
        do_reopened = config_get_boolean_ondemand("plugin:proc:/proc/net/stat/synproxy", "SYNPROXY connections reopened", CONFIG_ONDEMAND_ONDEMAND);
    }

    if(unlikely(!ff)) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/stat/synproxy");
        ff = procfile_open(config_get("plugin:proc:/proc/net/stat/synproxy", "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

    // make sure we have 3 lines
    size_t lines = procfile_lines(ff), l;
    if(unlikely(lines < 2)) {
        error("/proc/net/stat/synproxy has %zu lines, expected no less than 2. Disabling it.", lines);
        return 1;
    }

    unsigned long long entries = 0, syn_received = 0, cookie_invalid = 0, cookie_valid = 0, cookie_retrans = 0, conn_reopened = 0;

    // synproxy gives its values per CPU
    for(l = 1; l < lines ;l++) {
        int words = procfile_linewords(ff, l);
        if(unlikely(words < 6))
            continue;

        entries         += strtoull(procfile_lineword(ff, l, 0), NULL, 16);
        syn_received    += strtoull(procfile_lineword(ff, l, 1), NULL, 16);
        cookie_invalid  += strtoull(procfile_lineword(ff, l, 2), NULL, 16);
        cookie_valid    += strtoull(procfile_lineword(ff, l, 3), NULL, 16);
        cookie_retrans  += strtoull(procfile_lineword(ff, l, 4), NULL, 16);
        conn_reopened   += strtoull(procfile_lineword(ff, l, 5), NULL, 16);
    }

    unsigned long long events = entries + syn_received + cookie_invalid + cookie_valid + cookie_retrans + conn_reopened;

    RRDSET *st;

    // --------------------------------------------------------------------

    if((do_entries == CONFIG_ONDEMAND_ONDEMAND && events) || do_entries == CONFIG_ONDEMAND_YES) {
        do_entries = CONFIG_ONDEMAND_YES;

        st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_entries");
        if(unlikely(!st)) {
            st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_entries", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Entries Used", "entries", 3304, update_every, RRDSET_TYPE_LINE);

            rrddim_add(st, "entries", NULL, 1, 1, RRDDIM_ABSOLUTE);
        }
        else rrdset_next(st);

        rrddim_set(st, "entries", entries);
        rrdset_done(st);
    }

    // --------------------------------------------------------------------

    if((do_syns == CONFIG_ONDEMAND_ONDEMAND && events) || do_syns == CONFIG_ONDEMAND_YES) {
        do_syns = CONFIG_ONDEMAND_YES;

        st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_syn_received");
        if(unlikely(!st)) {
            st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_syn_received", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY SYN Packets received", "SYN/s", 3301, update_every, RRDSET_TYPE_LINE);

            rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
        }
        else rrdset_next(st);

        rrddim_set(st, "received", syn_received);
        rrdset_done(st);
    }

    // --------------------------------------------------------------------

    if((do_reopened == CONFIG_ONDEMAND_ONDEMAND && events) || do_reopened == CONFIG_ONDEMAND_YES) {
        do_reopened = CONFIG_ONDEMAND_YES;

        st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened");
        if(unlikely(!st)) {
            st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_conn_reopened", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY Connections Reopened", "connections/s", 3303, update_every, RRDSET_TYPE_LINE);

            rrddim_add(st, "reopened", NULL, 1, 1, RRDDIM_INCREMENTAL);
        }
        else rrdset_next(st);

        rrddim_set(st, "reopened", conn_reopened);
        rrdset_done(st);
    }

    // --------------------------------------------------------------------

    if((do_cookies == CONFIG_ONDEMAND_ONDEMAND && events) || do_cookies == CONFIG_ONDEMAND_YES) {
        do_cookies = CONFIG_ONDEMAND_YES;

        st = rrdset_find(RRD_TYPE_NET_STAT_NETFILTER "." RRD_TYPE_NET_STAT_SYNPROXY "_cookies");
        if(unlikely(!st)) {
            st = rrdset_create(RRD_TYPE_NET_STAT_NETFILTER, RRD_TYPE_NET_STAT_SYNPROXY "_cookies", NULL, RRD_TYPE_NET_STAT_SYNPROXY, NULL, "SYNPROXY TCP Cookies", "cookies/s", 3302, update_every, RRDSET_TYPE_LINE);

            rrddim_add(st, "valid", NULL, 1, 1, RRDDIM_INCREMENTAL);
            rrddim_add(st, "invalid", NULL, -1, 1, RRDDIM_INCREMENTAL);
            rrddim_add(st, "retransmits", NULL, 1, 1, RRDDIM_INCREMENTAL);
        }
        else rrdset_next(st);

        rrddim_set(st, "valid", cookie_valid);
        rrddim_set(st, "invalid", cookie_invalid);
        rrddim_set(st, "retransmits", cookie_retrans);
        rrdset_done(st);
    }

    return 0;
}
コード例 #23
0
ファイル: proc_net_snmp.c プロジェクト: dvigne/netdata
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;
}
コード例 #24
0
// read the whole mountinfo into a linked list
struct mountinfo *mountinfo_read(int do_statvfs) {
    char filename[FILENAME_MAX + 1];
    snprintfz(filename, FILENAME_MAX, "%s/proc/self/mountinfo", netdata_configured_host_prefix);
    procfile *ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
    if(unlikely(!ff)) {
        snprintfz(filename, FILENAME_MAX, "%s/proc/1/mountinfo", netdata_configured_host_prefix);
        ff = procfile_open(filename, " \t", PROCFILE_FLAG_DEFAULT);
        if(unlikely(!ff)) return NULL;
    }

    ff = procfile_readall(ff);
    if(unlikely(!ff))
        return NULL;

    struct mountinfo *root = NULL, *last = NULL, *mi = NULL;

    unsigned long l, lines = procfile_lines(ff);
    for(l = 0; l < lines ;l++) {
        if(unlikely(procfile_linewords(ff, l) < 5))
            continue;

        mi = mallocz(sizeof(struct mountinfo));

        unsigned long w = 0;
        mi->id = str2ul(procfile_lineword(ff, l, w)); w++;
        mi->parentid = str2ul(procfile_lineword(ff, l, w)); w++;

        char *major = procfile_lineword(ff, l, w), *minor; w++;
        for(minor = major; *minor && *minor != ':' ;minor++) ;

        if(unlikely(!*minor)) {
            error("Cannot parse major:minor on '%s' at line %lu of '%s'", major, l + 1, filename);
            freez(mi);
            continue;
        }

        *minor = '\0';
        minor++;

        mi->flags = 0;

        mi->major = str2ul(major);
        mi->minor = str2ul(minor);

        mi->root = strdupz(procfile_lineword(ff, l, w)); w++;
        mi->root_hash = simple_hash(mi->root);

        mi->mount_point = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
        mi->mount_point_hash = simple_hash(mi->mount_point);

        mi->persistent_id = strdupz(mi->mount_point);
        netdata_fix_chart_id(mi->persistent_id);
        mi->persistent_id_hash = simple_hash(mi->persistent_id);

        mi->mount_options = strdupz(procfile_lineword(ff, l, w)); w++;

        if(unlikely(is_read_only(mi->mount_options)))
            mi->flags |= MOUNTINFO_READONLY;

        // count the optional fields
/*
        unsigned long wo = w;
*/
        mi->optional_fields_count = 0;
        char *s = procfile_lineword(ff, l, w);
        while(*s && *s != '-') {
            w++;
            s = procfile_lineword(ff, l, w);
            mi->optional_fields_count++;
        }

/*
        if(unlikely(mi->optional_fields_count)) {
            // we have some optional fields
            // read them into a new array of pointers;

            mi->optional_fields = mallocz(mi->optional_fields_count * sizeof(char *));

            int i;
            for(i = 0; i < mi->optional_fields_count ; i++) {
                *mi->optional_fields[wo] = strdupz(procfile_lineword(ff, l, w));
                wo++;
            }
        }
        else
            mi->optional_fields = NULL;
*/

        if(likely(*s == '-')) {
            w++;

            mi->filesystem = strdupz(procfile_lineword(ff, l, w)); w++;
            mi->filesystem_hash = simple_hash(mi->filesystem);

            mi->mount_source = strdupz_decoding_octal(procfile_lineword(ff, l, w)); w++;
            mi->mount_source_hash = simple_hash(mi->mount_source);

            mi->super_options = strdupz(procfile_lineword(ff, l, w)); w++;

            if(unlikely(is_read_only(mi->super_options)))
                mi->flags |= MOUNTINFO_READONLY;

            if(unlikely(ME_DUMMY(mi->mount_source, mi->filesystem)))
                mi->flags |= MOUNTINFO_IS_DUMMY;

            if(unlikely(ME_REMOTE(mi->mount_source, mi->filesystem)))
                mi->flags |= MOUNTINFO_IS_REMOTE;

            // mark as BIND the duplicates (i.e. same filesystem + same source)
            if(do_statvfs) {
                struct stat buf;
                if(unlikely(stat(mi->mount_point, &buf) == -1)) {
                    mi->st_dev = 0;
                    mi->flags |= MOUNTINFO_NO_STAT;
                }
                else {
                    mi->st_dev = buf.st_dev;

                    struct mountinfo *mt;
                    for(mt = root; mt; mt = mt->next) {
                        if(unlikely(mt->st_dev == mi->st_dev && !(mt->flags & MOUNTINFO_IS_SAME_DEV))) {
                            if(strlen(mi->mount_point) < strlen(mt->mount_point))
                                mt->flags |= MOUNTINFO_IS_SAME_DEV;
                            else
                                mi->flags |= MOUNTINFO_IS_SAME_DEV;
                        }
                    }
                }
            }
            else {
                mi->st_dev = 0;
            }
        }
        else {
            mi->filesystem = NULL;
            mi->filesystem_hash = 0;

            mi->mount_source = NULL;
            mi->mount_source_hash = 0;

            mi->super_options = NULL;

            mi->st_dev = 0;
        }

        // check if it has size
        if(do_statvfs && !(mi->flags & MOUNTINFO_IS_DUMMY)) {
            struct statvfs buff_statvfs;
            if(unlikely(statvfs(mi->mount_point, &buff_statvfs) < 0)) {
                mi->flags |= MOUNTINFO_NO_STAT;
            }
            else if(unlikely(!buff_statvfs.f_blocks /* || !buff_statvfs.f_files */)) {
                mi->flags |= MOUNTINFO_NO_SIZE;
            }
        }

        // link it
        if(unlikely(!root))
            root = mi;
        else
            last->next = mi;

        last = mi;
        mi->next = NULL;

/*
#ifdef NETDATA_INTERNAL_CHECKS
        fprintf(stderr, "MOUNTINFO: %ld %ld %lu:%lu root '%s', persistent id '%s', mount point '%s', mount options '%s', filesystem '%s', mount source '%s', super options '%s'%s%s%s%s%s%s\n",
             mi->id,
             mi->parentid,
             mi->major,
             mi->minor,
             mi->root,
             mi->persistent_id,
                (mi->mount_point)?mi->mount_point:"",
                (mi->mount_options)?mi->mount_options:"",
                (mi->filesystem)?mi->filesystem:"",
                (mi->mount_source)?mi->mount_source:"",
                (mi->super_options)?mi->super_options:"",
                (mi->flags & MOUNTINFO_IS_DUMMY)?" DUMMY":"",
                (mi->flags & MOUNTINFO_IS_BIND)?" BIND":"",
                (mi->flags & MOUNTINFO_IS_REMOTE)?" REMOTE":"",
                (mi->flags & MOUNTINFO_NO_STAT)?" NOSTAT":"",
                (mi->flags & MOUNTINFO_NO_SIZE)?" NOSIZE":"",
                (mi->flags & MOUNTINFO_IS_SAME_DEV)?" SAMEDEV":""
        );
#endif
*/
    }

/* find if the mount options have "bind" in them
    {
        FILE *fp = setmntent(MOUNTED, "r");
        if (fp != NULL) {
            struct mntent mntbuf;
            struct mntent *mnt;
            char buf[4096 + 1];

            while ((mnt = getmntent_r(fp, &mntbuf, buf, 4096))) {
                char *bind = hasmntopt(mnt, "bind");
                if(unlikely(bind)) {
                    struct mountinfo *mi;
                    for(mi = root; mi ; mi = mi->next) {
                        if(unlikely(strcmp(mnt->mnt_dir, mi->mount_point) == 0)) {
                            fprintf(stderr, "Mount point '%s' is BIND\n", mi->mount_point);
                            mi->flags |= MOUNTINFO_IS_BIND;
                            break;
                        }
                    }

#ifdef NETDATA_INTERNAL_CHECKS
                    if(unlikely(!mi)) {
                        error("Mount point '%s' not found in /proc/self/mountinfo", mnt->mnt_dir);
                    }
#endif
                }
            }
            endmntent(fp);
        }
    }
*/

    procfile_close(ff);
    return root;
}
コード例 #25
0
ファイル: proc_net_ip_vs_stats.c プロジェクト: 178518/netdata
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;
}
コード例 #26
0
ファイル: proc_net_dev.c プロジェクト: bmaggard/netdata
int do_proc_net_dev(int update_every, usec_t dt) {
    static procfile *ff = NULL;
    static int enable_new_interfaces = -1, enable_ifb_interfaces = -1;
    static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1;

    if(dt) {};

    if(!ff) {
        char filename[FILENAME_MAX + 1];
        snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/net/dev");
        ff = procfile_open(config_get("plugin:proc:/proc/net/dev", "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(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_ONDEMAND);
    if(enable_ifb_interfaces == -1) enable_ifb_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable ifb interfaces", CONFIG_ONDEMAND_NO);

    if(do_bandwidth == -1)  do_bandwidth    = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
    if(do_packets == -1)    do_packets      = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
    if(do_errors == -1)     do_errors       = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "errors for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
    if(do_drops == -1)      do_drops        = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "drops for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
    if(do_fifo == -1)       do_fifo         = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
    if(do_compressed == -1) do_compressed   = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
    if(do_events == -1)     do_events       = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_ONDEMAND_ONDEMAND);

    uint32_t lines = procfile_lines(ff), l;

    char *iface;
    unsigned long long rbytes, rpackets, rerrors, rdrops, rfifo, rframe, rcompressed, rmulticast;
    unsigned long long tbytes, tpackets, terrors, tdrops, tfifo, tcollisions, tcarrier, tcompressed;

    for(l = 2; l < lines ;l++) {
        uint32_t words = procfile_linewords(ff, l);
        if(words < 17) continue;

        iface       = procfile_lineword(ff, l, 0);

        rbytes      = strtoull(procfile_lineword(ff, l, 1), NULL, 10);
        rpackets    = strtoull(procfile_lineword(ff, l, 2), NULL, 10);
        rerrors     = strtoull(procfile_lineword(ff, l, 3), NULL, 10);
        rdrops      = strtoull(procfile_lineword(ff, l, 4), NULL, 10);
        rfifo       = strtoull(procfile_lineword(ff, l, 5), NULL, 10);
        rframe      = strtoull(procfile_lineword(ff, l, 6), NULL, 10);
        rcompressed = strtoull(procfile_lineword(ff, l, 7), NULL, 10);
        rmulticast  = strtoull(procfile_lineword(ff, l, 8), NULL, 10);

        tbytes      = strtoull(procfile_lineword(ff, l, 9), NULL, 10);
        tpackets    = strtoull(procfile_lineword(ff, l, 10), NULL, 10);
        terrors     = strtoull(procfile_lineword(ff, l, 11), NULL, 10);
        tdrops      = strtoull(procfile_lineword(ff, l, 12), NULL, 10);
        tfifo       = strtoull(procfile_lineword(ff, l, 13), NULL, 10);
        tcollisions = strtoull(procfile_lineword(ff, l, 14), NULL, 10);
        tcarrier    = strtoull(procfile_lineword(ff, l, 15), NULL, 10);
        tcompressed = strtoull(procfile_lineword(ff, l, 16), NULL, 10);

        int ddo_bandwidth = do_bandwidth, ddo_packets = do_packets, ddo_errors = do_errors, ddo_drops = do_drops, ddo_fifo = do_fifo, ddo_compressed = do_compressed, ddo_events = do_events;

        int default_enable = enable_new_interfaces;

        // prevent unused interfaces from creating charts
        if(strcmp(iface, "lo") == 0)
            default_enable = 0;
        else {
            int len = strlen(iface);
            if(len >= 4 && strcmp(&iface[len-4], "-ifb") == 0)
                default_enable = enable_ifb_interfaces;
        }

        // check if the user wants it
        {
            char var_name[512 + 1];
            snprintfz(var_name, 512, "plugin:proc:/proc/net/dev:%s", iface);
            default_enable = config_get_boolean_ondemand(var_name, "enabled", default_enable);
            if(default_enable == CONFIG_ONDEMAND_NO) continue;
            if(default_enable == CONFIG_ONDEMAND_ONDEMAND && !rbytes && !tbytes) continue;

            ddo_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", ddo_bandwidth);
            ddo_packets = config_get_boolean_ondemand(var_name, "packets", ddo_packets);
            ddo_errors = config_get_boolean_ondemand(var_name, "errors", ddo_errors);
            ddo_drops = config_get_boolean_ondemand(var_name, "drops", ddo_drops);
            ddo_fifo = config_get_boolean_ondemand(var_name, "fifo", ddo_fifo);
            ddo_compressed = config_get_boolean_ondemand(var_name, "compressed", ddo_compressed);
            ddo_events = config_get_boolean_ondemand(var_name, "events", ddo_events);

            if(ddo_bandwidth == CONFIG_ONDEMAND_ONDEMAND && rbytes == 0 && tbytes == 0) ddo_bandwidth = 0;
            if(ddo_errors == CONFIG_ONDEMAND_ONDEMAND && rerrors == 0 && terrors == 0) ddo_errors = 0;
            if(ddo_drops == CONFIG_ONDEMAND_ONDEMAND && rdrops == 0 && tdrops == 0) ddo_drops = 0;
            if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND && rfifo == 0 && tfifo == 0) ddo_fifo = 0;
            if(ddo_compressed == CONFIG_ONDEMAND_ONDEMAND && rcompressed == 0 && tcompressed == 0) ddo_compressed = 0;
            if(ddo_events == CONFIG_ONDEMAND_ONDEMAND && rframe == 0 && tcollisions == 0 && tcarrier == 0) ddo_events = 0;

            // for absolute values, we need to switch the setting to 'yes'
            // to allow it refresh from now on
            // if(ddo_fifo == CONFIG_ONDEMAND_ONDEMAND) config_set(var_name, "fifo", "yes");
        }

        RRDSET *st;

        // --------------------------------------------------------------------

        if(ddo_bandwidth) {
            st = rrdset_find_bytype("net", iface);
            if(!st) {
                st = rrdset_create("net", iface, NULL, iface, "net.net", "Bandwidth", "kilobits/s", 7000, 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", rbytes);
            rrddim_set(st, "sent", tbytes);
            rrdset_done(st);
        }

        // --------------------------------------------------------------------

        if(ddo_packets) {
            st = rrdset_find_bytype("net_packets", iface);
            if(!st) {
                st = rrdset_create("net_packets", iface, NULL, iface, "net.packets", "Packets", "packets/s", 7001, update_every, RRDSET_TYPE_LINE);
                st->isdetail = 1;

                rrddim_add(st, "received", NULL, 1, 1, RRDDIM_INCREMENTAL);
                rrddim_add(st, "sent", NULL, -1, 1, RRDDIM_INCREMENTAL);
                rrddim_add(st, "multicast", NULL, 1, 1, RRDDIM_INCREMENTAL);
            }
            else rrdset_next(st);

            rrddim_set(st, "received", rpackets);
            rrddim_set(st, "sent", tpackets);
            rrddim_set(st, "multicast", rmulticast);
            rrdset_done(st);
        }

        // --------------------------------------------------------------------

        if(ddo_errors) {
            st = rrdset_find_bytype("net_errors", iface);
            if(!st) {
                st = rrdset_create("net_errors", iface, NULL, iface, "net.errors", "Interface Errors", "errors/s", 7002, update_every, RRDSET_TYPE_LINE);
                st->isdetail = 1;

                rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
                rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
            }
            else rrdset_next(st);

            rrddim_set(st, "inbound", rerrors);
            rrddim_set(st, "outbound", terrors);
            rrdset_done(st);
        }

        // --------------------------------------------------------------------

        if(ddo_drops) {
            st = rrdset_find_bytype("net_drops", iface);
            if(!st) {
                st = rrdset_create("net_drops", iface, NULL, iface, "net.drops", "Interface Drops", "drops/s", 7003, update_every, RRDSET_TYPE_LINE);
                st->isdetail = 1;

                rrddim_add(st, "inbound", NULL, 1, 1, RRDDIM_INCREMENTAL);
                rrddim_add(st, "outbound", NULL, -1, 1, RRDDIM_INCREMENTAL);
            }
            else rrdset_next(st);

            rrddim_set(st, "inbound", rdrops);
            rrddim_set(st, "outbound", tdrops);
            rrdset_done(st);
        }

        // --------------------------------------------------------------------

        if(ddo_fifo) {
            st = rrdset_find_bytype("net_fifo", iface);
            if(!st) {
                st = rrdset_create("net_fifo", iface, NULL, iface, "net.fifo", "Interface FIFO Buffer Errors", "errors", 7004, update_every, RRDSET_TYPE_LINE);
                st->isdetail = 1;

                rrddim_add(st, "receive", NULL, 1, 1, RRDDIM_INCREMENTAL);
                rrddim_add(st, "transmit", NULL, -1, 1, RRDDIM_INCREMENTAL);
            }
            else rrdset_next(st);

            rrddim_set(st, "receive", rfifo);
            rrddim_set(st, "transmit", tfifo);
            rrdset_done(st);
        }

        // --------------------------------------------------------------------

        if(ddo_compressed) {
            st = rrdset_find_bytype("net_compressed", iface);
            if(!st) {
                st = rrdset_create("net_compressed", iface, NULL, iface, "net.compressed", "Compressed Packets", "packets/s", 7005, update_every, RRDSET_TYPE_LINE);
                st->isdetail = 1;

                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", rcompressed);
            rrddim_set(st, "sent", tcompressed);
            rrdset_done(st);
        }

        // --------------------------------------------------------------------

        if(ddo_events) {
            st = rrdset_find_bytype("net_events", iface);
            if(!st) {
                st = rrdset_create("net_events", iface, NULL, iface, "net.events", "Network Interface Events", "events/s", 7006, update_every, RRDSET_TYPE_LINE);
                st->isdetail = 1;

                rrddim_add(st, "frames", NULL, 1, 1, RRDDIM_INCREMENTAL);
                rrddim_add(st, "collisions", NULL, -1, 1, RRDDIM_INCREMENTAL);
                rrddim_add(st, "carrier", NULL, -1, 1, RRDDIM_INCREMENTAL);
            }
            else rrdset_next(st);

            rrddim_set(st, "frames", rframe);
            rrddim_set(st, "collisions", tcollisions);
            rrddim_set(st, "carrier", tcarrier);
            rrdset_done(st);
        }
    }

    return 0;
}
コード例 #27
0
ファイル: proc_interrupts.c プロジェクト: acecommerce/netdata
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;
}
コード例 #28
0
ファイル: proc_vmstat.c プロジェクト: 0-T-0/netdata
int do_proc_vmstat(int update_every, unsigned long long dt) {
	static procfile *ff = NULL;
	static int do_swapio = -1, do_io = -1, do_pgfaults = -1, gen_hashes = -1;

	// static uint32_t hash_allocstall = -1;
	// static uint32_t hash_compact_blocks_moved = -1;
	// static uint32_t hash_compact_fail = -1;
	// static uint32_t hash_compact_pagemigrate_failed = -1;
	// static uint32_t hash_compact_pages_moved = -1;
	// static uint32_t hash_compact_stall = -1;
	// static uint32_t hash_compact_success = -1;
	// static uint32_t hash_htlb_buddy_alloc_fail = -1;
	// static uint32_t hash_htlb_buddy_alloc_success = -1;
	// static uint32_t hash_kswapd_high_wmark_hit_quickly = -1;
	// static uint32_t hash_kswapd_inodesteal = -1;
	// static uint32_t hash_kswapd_low_wmark_hit_quickly = -1;
	// static uint32_t hash_kswapd_skip_congestion_wait = -1;
	// static uint32_t hash_nr_active_anon = -1;
	// static uint32_t hash_nr_active_file = -1;
	// static uint32_t hash_nr_anon_pages = -1;
	// static uint32_t hash_nr_anon_transparent_hugepages = -1;
	// static uint32_t hash_nr_bounce = -1;
	// static uint32_t hash_nr_dirtied = -1;
	// static uint32_t hash_nr_dirty = -1;
	// static uint32_t hash_nr_dirty_background_threshold = -1;
	// static uint32_t hash_nr_dirty_threshold = -1;
	// static uint32_t hash_nr_file_pages = -1;
	// static uint32_t hash_nr_free_pages = -1;
	// static uint32_t hash_nr_inactive_anon = -1;
	// static uint32_t hash_nr_inactive_file = -1;
	// static uint32_t hash_nr_isolated_anon = -1;
	// static uint32_t hash_nr_isolated_file = -1;
	// static uint32_t hash_nr_kernel_stack = -1;
	// static uint32_t hash_nr_mapped = -1;
	// static uint32_t hash_nr_mlock = -1;
	// static uint32_t hash_nr_page_table_pages = -1;
	// static uint32_t hash_nr_shmem = -1;
	// static uint32_t hash_nr_slab_reclaimable = -1;
	// static uint32_t hash_nr_slab_unreclaimable = -1;
	// static uint32_t hash_nr_unevictable = -1;
	// static uint32_t hash_nr_unstable = -1;
	// static uint32_t hash_nr_vmscan_immediate_reclaim = -1;
	// static uint32_t hash_nr_vmscan_write = -1;
	// static uint32_t hash_nr_writeback = -1;
	// static uint32_t hash_nr_writeback_temp = -1;
	// static uint32_t hash_nr_written = -1;
	// static uint32_t hash_pageoutrun = -1;
	// static uint32_t hash_pgactivate = -1;
	// static uint32_t hash_pgalloc_dma = -1;
	// static uint32_t hash_pgalloc_dma32 = -1;
	// static uint32_t hash_pgalloc_movable = -1;
	// static uint32_t hash_pgalloc_normal = -1;
	// static uint32_t hash_pgdeactivate = -1;
	static uint32_t hash_pgfault = -1;
	// static uint32_t hash_pgfree = -1;
	// static uint32_t hash_pginodesteal = -1;
	static uint32_t hash_pgmajfault = -1;
	static uint32_t hash_pgpgin = -1;
	static uint32_t hash_pgpgout = -1;
	// static uint32_t hash_pgrefill_dma = -1;
	// static uint32_t hash_pgrefill_dma32 = -1;
	// static uint32_t hash_pgrefill_movable = -1;
	// static uint32_t hash_pgrefill_normal = -1;
	// static uint32_t hash_pgrotated = -1;
	// static uint32_t hash_pgscan_direct_dma = -1;
	// static uint32_t hash_pgscan_direct_dma32 = -1;
	// static uint32_t hash_pgscan_direct_movable = -1;
	// static uint32_t hash_pgscan_direct_normal = -1;
	// static uint32_t hash_pgscan_kswapd_dma = -1;
	// static uint32_t hash_pgscan_kswapd_dma32 = -1;
	// static uint32_t hash_pgscan_kswapd_movable = -1;
	// static uint32_t hash_pgscan_kswapd_normal = -1;
	// static uint32_t hash_pgsteal_direct_dma = -1;
	// static uint32_t hash_pgsteal_direct_dma32 = -1;
	// static uint32_t hash_pgsteal_direct_movable = -1;
	// static uint32_t hash_pgsteal_direct_normal = -1;
	// static uint32_t hash_pgsteal_kswapd_dma = -1;
	// static uint32_t hash_pgsteal_kswapd_dma32 = -1;
	// static uint32_t hash_pgsteal_kswapd_movable = -1;
	// static uint32_t hash_pgsteal_kswapd_normal = -1;
	static uint32_t hash_pswpin = -1;
	static uint32_t hash_pswpout = -1;
	// static uint32_t hash_slabs_scanned = -1;
	// static uint32_t hash_thp_collapse_alloc = -1;
	// static uint32_t hash_thp_collapse_alloc_failed = -1;
	// static uint32_t hash_thp_fault_alloc = -1;
	// static uint32_t hash_thp_fault_fallback = -1;
	// static uint32_t hash_thp_split = -1;
	// static uint32_t hash_unevictable_pgs_cleared = -1;
	// static uint32_t hash_unevictable_pgs_culled = -1;
	// static uint32_t hash_unevictable_pgs_mlocked = -1;
	// static uint32_t hash_unevictable_pgs_mlockfreed = -1;
	// static uint32_t hash_unevictable_pgs_munlocked = -1;
	// static uint32_t hash_unevictable_pgs_rescued = -1;
	// static uint32_t hash_unevictable_pgs_scanned = -1;
	// static uint32_t hash_unevictable_pgs_stranded = -1;

	if(gen_hashes != 1) {
		gen_hashes = 1;
		// hash_allocstall = simple_hash("allocstall");
		// hash_compact_blocks_moved = simple_hash("compact_blocks_moved");
		// hash_compact_fail = simple_hash("compact_fail");
		// hash_compact_pagemigrate_failed = simple_hash("compact_pagemigrate_failed");
		// hash_compact_pages_moved = simple_hash("compact_pages_moved");
		// hash_compact_stall = simple_hash("compact_stall");
		// hash_compact_success = simple_hash("compact_success");
		// hash_htlb_buddy_alloc_fail = simple_hash("htlb_buddy_alloc_fail");
		// hash_htlb_buddy_alloc_success = simple_hash("htlb_buddy_alloc_success");
		// hash_kswapd_high_wmark_hit_quickly = simple_hash("kswapd_high_wmark_hit_quickly");
		// hash_kswapd_inodesteal = simple_hash("kswapd_inodesteal");
		// hash_kswapd_low_wmark_hit_quickly = simple_hash("kswapd_low_wmark_hit_quickly");
		// hash_kswapd_skip_congestion_wait = simple_hash("kswapd_skip_congestion_wait");
		// hash_nr_active_anon = simple_hash("nr_active_anon");
		// hash_nr_active_file = simple_hash("nr_active_file");
		// hash_nr_anon_pages = simple_hash("nr_anon_pages");
		// hash_nr_anon_transparent_hugepages = simple_hash("nr_anon_transparent_hugepages");
		// hash_nr_bounce = simple_hash("nr_bounce");
		// hash_nr_dirtied = simple_hash("nr_dirtied");
		// hash_nr_dirty = simple_hash("nr_dirty");
		// hash_nr_dirty_background_threshold = simple_hash("nr_dirty_background_threshold");
		// hash_nr_dirty_threshold = simple_hash("nr_dirty_threshold");
		// hash_nr_file_pages = simple_hash("nr_file_pages");
		// hash_nr_free_pages = simple_hash("nr_free_pages");
		// hash_nr_inactive_anon = simple_hash("nr_inactive_anon");
		// hash_nr_inactive_file = simple_hash("nr_inactive_file");
		// hash_nr_isolated_anon = simple_hash("nr_isolated_anon");
		// hash_nr_isolated_file = simple_hash("nr_isolated_file");
		// hash_nr_kernel_stack = simple_hash("nr_kernel_stack");
		// hash_nr_mapped = simple_hash("nr_mapped");
		// hash_nr_mlock = simple_hash("nr_mlock");
		// hash_nr_page_table_pages = simple_hash("nr_page_table_pages");
		// hash_nr_shmem = simple_hash("nr_shmem");
		// hash_nr_slab_reclaimable = simple_hash("nr_slab_reclaimable");
		// hash_nr_slab_unreclaimable = simple_hash("nr_slab_unreclaimable");
		// hash_nr_unevictable = simple_hash("nr_unevictable");
		// hash_nr_unstable = simple_hash("nr_unstable");
		// hash_nr_vmscan_immediate_reclaim = simple_hash("nr_vmscan_immediate_reclaim");
		// hash_nr_vmscan_write = simple_hash("nr_vmscan_write");
		// hash_nr_writeback = simple_hash("nr_writeback");
		// hash_nr_writeback_temp = simple_hash("nr_writeback_temp");
		// hash_nr_written = simple_hash("nr_written");
		// hash_pageoutrun = simple_hash("pageoutrun");
		// hash_pgactivate = simple_hash("pgactivate");
		// hash_pgalloc_dma = simple_hash("pgalloc_dma");
		// hash_pgalloc_dma32 = simple_hash("pgalloc_dma32");
		// hash_pgalloc_movable = simple_hash("pgalloc_movable");
		// hash_pgalloc_normal = simple_hash("pgalloc_normal");
		// hash_pgdeactivate = simple_hash("pgdeactivate");
		hash_pgfault = simple_hash("pgfault");
		// hash_pgfree = simple_hash("pgfree");
		// hash_pginodesteal = simple_hash("pginodesteal");
		hash_pgmajfault = simple_hash("pgmajfault");
		hash_pgpgin = simple_hash("pgpgin");
		hash_pgpgout = simple_hash("pgpgout");
		// hash_pgrefill_dma = simple_hash("pgrefill_dma");
		// hash_pgrefill_dma32 = simple_hash("pgrefill_dma32");
		// hash_pgrefill_movable = simple_hash("pgrefill_movable");
		// hash_pgrefill_normal = simple_hash("pgrefill_normal");
		// hash_pgrotated = simple_hash("pgrotated");
		// hash_pgscan_direct_dma = simple_hash("pgscan_direct_dma");
		// hash_pgscan_direct_dma32 = simple_hash("pgscan_direct_dma32");
		// hash_pgscan_direct_movable = simple_hash("pgscan_direct_movable");
		// hash_pgscan_direct_normal = simple_hash("pgscan_direct_normal");
		// hash_pgscan_kswapd_dma = simple_hash("pgscan_kswapd_dma");
		// hash_pgscan_kswapd_dma32 = simple_hash("pgscan_kswapd_dma32");
		// hash_pgscan_kswapd_movable = simple_hash("pgscan_kswapd_movable");
		// hash_pgscan_kswapd_normal = simple_hash("pgscan_kswapd_normal");
		// hash_pgsteal_direct_dma = simple_hash("pgsteal_direct_dma");
		// hash_pgsteal_direct_dma32 = simple_hash("pgsteal_direct_dma32");
		// hash_pgsteal_direct_movable = simple_hash("pgsteal_direct_movable");
		// hash_pgsteal_direct_normal = simple_hash("pgsteal_direct_normal");
		// hash_pgsteal_kswapd_dma = simple_hash("pgsteal_kswapd_dma");
		// hash_pgsteal_kswapd_dma32 = simple_hash("pgsteal_kswapd_dma32");
		// hash_pgsteal_kswapd_movable = simple_hash("pgsteal_kswapd_movable");
		// hash_pgsteal_kswapd_normal = simple_hash("pgsteal_kswapd_normal");
		hash_pswpin = simple_hash("pswpin");
		hash_pswpout = simple_hash("pswpout");
		// hash_slabs_scanned = simple_hash("slabs_scanned");
		// hash_thp_collapse_alloc = simple_hash("thp_collapse_alloc");
		// hash_thp_collapse_alloc_failed = simple_hash("thp_collapse_alloc_failed");
		// hash_thp_fault_alloc = simple_hash("thp_fault_alloc");
		// hash_thp_fault_fallback = simple_hash("thp_fault_fallback");
		// hash_thp_split = simple_hash("thp_split");
		// hash_unevictable_pgs_cleared = simple_hash("unevictable_pgs_cleared");
		// hash_unevictable_pgs_culled = simple_hash("unevictable_pgs_culled");
		// hash_unevictable_pgs_mlocked = simple_hash("unevictable_pgs_mlocked");
		// hash_unevictable_pgs_mlockfreed = simple_hash("unevictable_pgs_mlockfreed");
		// hash_unevictable_pgs_munlocked = simple_hash("unevictable_pgs_munlocked");
		// hash_unevictable_pgs_rescued = simple_hash("unevictable_pgs_rescued");
		// hash_unevictable_pgs_scanned = simple_hash("unevictable_pgs_scanned");
		// hash_unevictable_pgs_stranded = simple_hash("unevictable_pgs_stranded");
	}

	if(do_swapio == -1)	do_swapio = config_get_boolean("plugin:proc:/proc/vmstat", "swap i/o", 1);
	if(do_io == -1)		do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1);
	if(do_pgfaults == -1)	do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1);

	if(dt) {};

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/vmstat");
		ff = procfile_open(config_get("plugin:proc:/proc/vmstat", "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 allocstall = 0ULL;
	// unsigned long long compact_blocks_moved = 0ULL;
	// unsigned long long compact_fail = 0ULL;
	// unsigned long long compact_pagemigrate_failed = 0ULL;
	// unsigned long long compact_pages_moved = 0ULL;
	// unsigned long long compact_stall = 0ULL;
	// unsigned long long compact_success = 0ULL;
	// unsigned long long htlb_buddy_alloc_fail = 0ULL;
	// unsigned long long htlb_buddy_alloc_success = 0ULL;
	// unsigned long long kswapd_high_wmark_hit_quickly = 0ULL;
	// unsigned long long kswapd_inodesteal = 0ULL;
	// unsigned long long kswapd_low_wmark_hit_quickly = 0ULL;
	// unsigned long long kswapd_skip_congestion_wait = 0ULL;
	// unsigned long long nr_active_anon = 0ULL;
	// unsigned long long nr_active_file = 0ULL;
	// unsigned long long nr_anon_pages = 0ULL;
	// unsigned long long nr_anon_transparent_hugepages = 0ULL;
	// unsigned long long nr_bounce = 0ULL;
	// unsigned long long nr_dirtied = 0ULL;
	// unsigned long long nr_dirty = 0ULL;
	// unsigned long long nr_dirty_background_threshold = 0ULL;
	// unsigned long long nr_dirty_threshold = 0ULL;
	// unsigned long long nr_file_pages = 0ULL;
	// unsigned long long nr_free_pages = 0ULL;
	// unsigned long long nr_inactive_anon = 0ULL;
	// unsigned long long nr_inactive_file = 0ULL;
	// unsigned long long nr_isolated_anon = 0ULL;
	// unsigned long long nr_isolated_file = 0ULL;
	// unsigned long long nr_kernel_stack = 0ULL;
	// unsigned long long nr_mapped = 0ULL;
	// unsigned long long nr_mlock = 0ULL;
	// unsigned long long nr_page_table_pages = 0ULL;
	// unsigned long long nr_shmem = 0ULL;
	// unsigned long long nr_slab_reclaimable = 0ULL;
	// unsigned long long nr_slab_unreclaimable = 0ULL;
	// unsigned long long nr_unevictable = 0ULL;
	// unsigned long long nr_unstable = 0ULL;
	// unsigned long long nr_vmscan_immediate_reclaim = 0ULL;
	// unsigned long long nr_vmscan_write = 0ULL;
	// unsigned long long nr_writeback = 0ULL;
	// unsigned long long nr_writeback_temp = 0ULL;
	// unsigned long long nr_written = 0ULL;
	// unsigned long long pageoutrun = 0ULL;
	// unsigned long long pgactivate = 0ULL;
	// unsigned long long pgalloc_dma = 0ULL;
	// unsigned long long pgalloc_dma32 = 0ULL;
	// unsigned long long pgalloc_movable = 0ULL;
	// unsigned long long pgalloc_normal = 0ULL;
	// unsigned long long pgdeactivate = 0ULL;
	unsigned long long pgfault = 0ULL;
	// unsigned long long pgfree = 0ULL;
	// unsigned long long pginodesteal = 0ULL;
	unsigned long long pgmajfault = 0ULL;
	unsigned long long pgpgin = 0ULL;
	unsigned long long pgpgout = 0ULL;
	// unsigned long long pgrefill_dma = 0ULL;
	// unsigned long long pgrefill_dma32 = 0ULL;
	// unsigned long long pgrefill_movable = 0ULL;
	// unsigned long long pgrefill_normal = 0ULL;
	// unsigned long long pgrotated = 0ULL;
	// unsigned long long pgscan_direct_dma = 0ULL;
	// unsigned long long pgscan_direct_dma32 = 0ULL;
	// unsigned long long pgscan_direct_movable = 0ULL;
	// unsigned long long pgscan_direct_normal = 0ULL;
	// unsigned long long pgscan_kswapd_dma = 0ULL;
	// unsigned long long pgscan_kswapd_dma32 = 0ULL;
	// unsigned long long pgscan_kswapd_movable = 0ULL;
	// unsigned long long pgscan_kswapd_normal = 0ULL;
	// unsigned long long pgsteal_direct_dma = 0ULL;
	// unsigned long long pgsteal_direct_dma32 = 0ULL;
	// unsigned long long pgsteal_direct_movable = 0ULL;
	// unsigned long long pgsteal_direct_normal = 0ULL;
	// unsigned long long pgsteal_kswapd_dma = 0ULL;
	// unsigned long long pgsteal_kswapd_dma32 = 0ULL;
	// unsigned long long pgsteal_kswapd_movable = 0ULL;
	// unsigned long long pgsteal_kswapd_normal = 0ULL;
	unsigned long long pswpin = 0ULL;
	unsigned long long pswpout = 0ULL;
	// unsigned long long slabs_scanned = 0ULL;
	// unsigned long long thp_collapse_alloc = 0ULL;
	// unsigned long long thp_collapse_alloc_failed = 0ULL;
	// unsigned long long thp_fault_alloc = 0ULL;
	// unsigned long long thp_fault_fallback = 0ULL;
	// unsigned long long thp_split = 0ULL;
	// unsigned long long unevictable_pgs_cleared = 0ULL;
	// unsigned long long unevictable_pgs_culled = 0ULL;
	// unsigned long long unevictable_pgs_mlocked = 0ULL;
	// unsigned long long unevictable_pgs_mlockfreed = 0ULL;
	// unsigned long long unevictable_pgs_munlocked = 0ULL;
	// unsigned long long unevictable_pgs_rescued = 0ULL;
	// unsigned long long unevictable_pgs_scanned = 0ULL;
	// unsigned long long unevictable_pgs_stranded = 0ULL;

	for(l = 0; l < lines ;l++) {
		words = procfile_linewords(ff, l);
		if(words < 2) {
			if(words) error("Cannot read /proc/vmstat line %d. Expected 2 params, read %d.", l, words);
			continue;
		}

		char *name = procfile_lineword(ff, l, 0);
		char * value = procfile_lineword(ff, l, 1);
		if(!name || !*name || !value || !*value) continue;

		uint32_t hash = simple_hash(name);

		if(0) ;
		// else if(hash == hash_allocstall && strcmp(name, "allocstall") == 0) allocstall = strtoull(value, NULL, 10);
		// else if(hash == hash_compact_blocks_moved && strcmp(name, "compact_blocks_moved") == 0) compact_blocks_moved = strtoull(value, NULL, 10);
		// else if(hash == hash_compact_fail && strcmp(name, "compact_fail") == 0) compact_fail = strtoull(value, NULL, 10);
		// else if(hash == hash_compact_pagemigrate_failed && strcmp(name, "compact_pagemigrate_failed") == 0) compact_pagemigrate_failed = strtoull(value, NULL, 10);
		// else if(hash == hash_compact_pages_moved && strcmp(name, "compact_pages_moved") == 0) compact_pages_moved = strtoull(value, NULL, 10);
		// else if(hash == hash_compact_stall && strcmp(name, "compact_stall") == 0) compact_stall = strtoull(value, NULL, 10);
		// else if(hash == hash_compact_success && strcmp(name, "compact_success") == 0) compact_success = strtoull(value, NULL, 10);
		// else if(hash == hash_htlb_buddy_alloc_fail && strcmp(name, "htlb_buddy_alloc_fail") == 0) htlb_buddy_alloc_fail = strtoull(value, NULL, 10);
		// else if(hash == hash_htlb_buddy_alloc_success && strcmp(name, "htlb_buddy_alloc_success") == 0) htlb_buddy_alloc_success = strtoull(value, NULL, 10);
		// else if(hash == hash_kswapd_high_wmark_hit_quickly && strcmp(name, "kswapd_high_wmark_hit_quickly") == 0) kswapd_high_wmark_hit_quickly = strtoull(value, NULL, 10);
		// else if(hash == hash_kswapd_inodesteal && strcmp(name, "kswapd_inodesteal") == 0) kswapd_inodesteal = strtoull(value, NULL, 10);
		// else if(hash == hash_kswapd_low_wmark_hit_quickly && strcmp(name, "kswapd_low_wmark_hit_quickly") == 0) kswapd_low_wmark_hit_quickly = strtoull(value, NULL, 10);
		// else if(hash == hash_kswapd_skip_congestion_wait && strcmp(name, "kswapd_skip_congestion_wait") == 0) kswapd_skip_congestion_wait = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_active_anon && strcmp(name, "nr_active_anon") == 0) nr_active_anon = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_active_file && strcmp(name, "nr_active_file") == 0) nr_active_file = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_anon_pages && strcmp(name, "nr_anon_pages") == 0) nr_anon_pages = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_anon_transparent_hugepages && strcmp(name, "nr_anon_transparent_hugepages") == 0) nr_anon_transparent_hugepages = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_bounce && strcmp(name, "nr_bounce") == 0) nr_bounce = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_dirtied && strcmp(name, "nr_dirtied") == 0) nr_dirtied = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_dirty && strcmp(name, "nr_dirty") == 0) nr_dirty = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_dirty_background_threshold && strcmp(name, "nr_dirty_background_threshold") == 0) nr_dirty_background_threshold = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_dirty_threshold && strcmp(name, "nr_dirty_threshold") == 0) nr_dirty_threshold = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_file_pages && strcmp(name, "nr_file_pages") == 0) nr_file_pages = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_free_pages && strcmp(name, "nr_free_pages") == 0) nr_free_pages = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_inactive_anon && strcmp(name, "nr_inactive_anon") == 0) nr_inactive_anon = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_inactive_file && strcmp(name, "nr_inactive_file") == 0) nr_inactive_file = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_isolated_anon && strcmp(name, "nr_isolated_anon") == 0) nr_isolated_anon = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_isolated_file && strcmp(name, "nr_isolated_file") == 0) nr_isolated_file = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_kernel_stack && strcmp(name, "nr_kernel_stack") == 0) nr_kernel_stack = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_mapped && strcmp(name, "nr_mapped") == 0) nr_mapped = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_mlock && strcmp(name, "nr_mlock") == 0) nr_mlock = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_page_table_pages && strcmp(name, "nr_page_table_pages") == 0) nr_page_table_pages = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_shmem && strcmp(name, "nr_shmem") == 0) nr_shmem = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_slab_reclaimable && strcmp(name, "nr_slab_reclaimable") == 0) nr_slab_reclaimable = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_slab_unreclaimable && strcmp(name, "nr_slab_unreclaimable") == 0) nr_slab_unreclaimable = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_unevictable && strcmp(name, "nr_unevictable") == 0) nr_unevictable = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_unstable && strcmp(name, "nr_unstable") == 0) nr_unstable = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_vmscan_immediate_reclaim && strcmp(name, "nr_vmscan_immediate_reclaim") == 0) nr_vmscan_immediate_reclaim = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_vmscan_write && strcmp(name, "nr_vmscan_write") == 0) nr_vmscan_write = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_writeback && strcmp(name, "nr_writeback") == 0) nr_writeback = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_writeback_temp && strcmp(name, "nr_writeback_temp") == 0) nr_writeback_temp = strtoull(value, NULL, 10);
		// else if(hash == hash_nr_written && strcmp(name, "nr_written") == 0) nr_written = strtoull(value, NULL, 10);
		// else if(hash == hash_pageoutrun && strcmp(name, "pageoutrun") == 0) pageoutrun = strtoull(value, NULL, 10);
		// else if(hash == hash_pgactivate && strcmp(name, "pgactivate") == 0) pgactivate = strtoull(value, NULL, 10);
		// else if(hash == hash_pgalloc_dma && strcmp(name, "pgalloc_dma") == 0) pgalloc_dma = strtoull(value, NULL, 10);
		// else if(hash == hash_pgalloc_dma32 && strcmp(name, "pgalloc_dma32") == 0) pgalloc_dma32 = strtoull(value, NULL, 10);
		// else if(hash == hash_pgalloc_movable && strcmp(name, "pgalloc_movable") == 0) pgalloc_movable = strtoull(value, NULL, 10);
		// else if(hash == hash_pgalloc_normal && strcmp(name, "pgalloc_normal") == 0) pgalloc_normal = strtoull(value, NULL, 10);
		// else if(hash == hash_pgdeactivate && strcmp(name, "pgdeactivate") == 0) pgdeactivate = strtoull(value, NULL, 10);
		else if(hash == hash_pgfault && strcmp(name, "pgfault") == 0) pgfault = strtoull(value, NULL, 10);
		// else if(hash == hash_pgfree && strcmp(name, "pgfree") == 0) pgfree = strtoull(value, NULL, 10);
		// else if(hash == hash_pginodesteal && strcmp(name, "pginodesteal") == 0) pginodesteal = strtoull(value, NULL, 10);
		else if(hash == hash_pgmajfault && strcmp(name, "pgmajfault") == 0) pgmajfault = strtoull(value, NULL, 10);
		else if(hash == hash_pgpgin && strcmp(name, "pgpgin") == 0) pgpgin = strtoull(value, NULL, 10);
		else if(hash == hash_pgpgout && strcmp(name, "pgpgout") == 0) pgpgout = strtoull(value, NULL, 10);
		// else if(hash == hash_pgrefill_dma && strcmp(name, "pgrefill_dma") == 0) pgrefill_dma = strtoull(value, NULL, 10);
		// else if(hash == hash_pgrefill_dma32 && strcmp(name, "pgrefill_dma32") == 0) pgrefill_dma32 = strtoull(value, NULL, 10);
		// else if(hash == hash_pgrefill_movable && strcmp(name, "pgrefill_movable") == 0) pgrefill_movable = strtoull(value, NULL, 10);
		// else if(hash == hash_pgrefill_normal && strcmp(name, "pgrefill_normal") == 0) pgrefill_normal = strtoull(value, NULL, 10);
		// else if(hash == hash_pgrotated && strcmp(name, "pgrotated") == 0) pgrotated = strtoull(value, NULL, 10);
		// else if(hash == hash_pgscan_direct_dma && strcmp(name, "pgscan_direct_dma") == 0) pgscan_direct_dma = strtoull(value, NULL, 10);
		// else if(hash == hash_pgscan_direct_dma32 && strcmp(name, "pgscan_direct_dma32") == 0) pgscan_direct_dma32 = strtoull(value, NULL, 10);
		// else if(hash == hash_pgscan_direct_movable && strcmp(name, "pgscan_direct_movable") == 0) pgscan_direct_movable = strtoull(value, NULL, 10);
		// else if(hash == hash_pgscan_direct_normal && strcmp(name, "pgscan_direct_normal") == 0) pgscan_direct_normal = strtoull(value, NULL, 10);
		// else if(hash == hash_pgscan_kswapd_dma && strcmp(name, "pgscan_kswapd_dma") == 0) pgscan_kswapd_dma = strtoull(value, NULL, 10);
		// else if(hash == hash_pgscan_kswapd_dma32 && strcmp(name, "pgscan_kswapd_dma32") == 0) pgscan_kswapd_dma32 = strtoull(value, NULL, 10);
		// else if(hash == hash_pgscan_kswapd_movable && strcmp(name, "pgscan_kswapd_movable") == 0) pgscan_kswapd_movable = strtoull(value, NULL, 10);
		// else if(hash == hash_pgscan_kswapd_normal && strcmp(name, "pgscan_kswapd_normal") == 0) pgscan_kswapd_normal = strtoull(value, NULL, 10);
		// else if(hash == hash_pgsteal_direct_dma && strcmp(name, "pgsteal_direct_dma") == 0) pgsteal_direct_dma = strtoull(value, NULL, 10);
		// else if(hash == hash_pgsteal_direct_dma32 && strcmp(name, "pgsteal_direct_dma32") == 0) pgsteal_direct_dma32 = strtoull(value, NULL, 10);
		// else if(hash == hash_pgsteal_direct_movable && strcmp(name, "pgsteal_direct_movable") == 0) pgsteal_direct_movable = strtoull(value, NULL, 10);
		// else if(hash == hash_pgsteal_direct_normal && strcmp(name, "pgsteal_direct_normal") == 0) pgsteal_direct_normal = strtoull(value, NULL, 10);
		// else if(hash == hash_pgsteal_kswapd_dma && strcmp(name, "pgsteal_kswapd_dma") == 0) pgsteal_kswapd_dma = strtoull(value, NULL, 10);
		// else if(hash == hash_pgsteal_kswapd_dma32 && strcmp(name, "pgsteal_kswapd_dma32") == 0) pgsteal_kswapd_dma32 = strtoull(value, NULL, 10);
		// else if(hash == hash_pgsteal_kswapd_movable && strcmp(name, "pgsteal_kswapd_movable") == 0) pgsteal_kswapd_movable = strtoull(value, NULL, 10);
		// else if(hash == hash_pgsteal_kswapd_normal && strcmp(name, "pgsteal_kswapd_normal") == 0) pgsteal_kswapd_normal = strtoull(value, NULL, 10);
		else if(hash == hash_pswpin && strcmp(name, "pswpin") == 0) pswpin = strtoull(value, NULL, 10);
		else if(hash == hash_pswpout && strcmp(name, "pswpout") == 0) pswpout = strtoull(value, NULL, 10);
		// else if(hash == hash_slabs_scanned && strcmp(name, "slabs_scanned") == 0) slabs_scanned = strtoull(value, NULL, 10);
		// else if(hash == hash_thp_collapse_alloc && strcmp(name, "thp_collapse_alloc") == 0) thp_collapse_alloc = strtoull(value, NULL, 10);
		// else if(hash == hash_thp_collapse_alloc_failed && strcmp(name, "thp_collapse_alloc_failed") == 0) thp_collapse_alloc_failed = strtoull(value, NULL, 10);
		// else if(hash == hash_thp_fault_alloc && strcmp(name, "thp_fault_alloc") == 0) thp_fault_alloc = strtoull(value, NULL, 10);
		// else if(hash == hash_thp_fault_fallback && strcmp(name, "thp_fault_fallback") == 0) thp_fault_fallback = strtoull(value, NULL, 10);
		// else if(hash == hash_thp_split && strcmp(name, "thp_split") == 0) thp_split = strtoull(value, NULL, 10);
		// else if(hash == hash_unevictable_pgs_cleared && strcmp(name, "unevictable_pgs_cleared") == 0) unevictable_pgs_cleared = strtoull(value, NULL, 10);
		// else if(hash == hash_unevictable_pgs_culled && strcmp(name, "unevictable_pgs_culled") == 0) unevictable_pgs_culled = strtoull(value, NULL, 10);
		// else if(hash == hash_unevictable_pgs_mlocked && strcmp(name, "unevictable_pgs_mlocked") == 0) unevictable_pgs_mlocked = strtoull(value, NULL, 10);
		// else if(hash == hash_unevictable_pgs_mlockfreed && strcmp(name, "unevictable_pgs_mlockfreed") == 0) unevictable_pgs_mlockfreed = strtoull(value, NULL, 10);
		// else if(hash == hash_unevictable_pgs_munlocked && strcmp(name, "unevictable_pgs_munlocked") == 0) unevictable_pgs_munlocked = strtoull(value, NULL, 10);
		// else if(hash == hash_unevictable_pgs_rescued && strcmp(name, "unevictable_pgs_rescued") == 0) unevictable_pgs_rescued = strtoull(value, NULL, 10);
		// else if(hash == hash_unevictable_pgs_scanned && strcmp(name, "unevictable_pgs_scanned") == 0) unevictable_pgs_scanned = strtoull(value, NULL, 10);
		// else if(hash == hash_unevictable_pgs_stranded && strcmp(name, "unevictable_pgs_stranded") == 0) unevictable_pgs_stranded = strtoull(value, NULL, 10);
	}

	// --------------------------------------------------------------------

	if(do_swapio) {
		static RRDSET *st_swapio = NULL;
		if(!st_swapio) {
			st_swapio = rrdset_create("system", "swapio", NULL, "swap", NULL, "Swap I/O", "kilobytes/s", 250, update_every, RRDSET_TYPE_AREA);

			rrddim_add(st_swapio, "in",  NULL, sysconf(_SC_PAGESIZE), 1024, RRDDIM_INCREMENTAL);
			rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st_swapio);

		rrddim_set(st_swapio, "in", pswpin);
		rrddim_set(st_swapio, "out", pswpout);
		rrdset_done(st_swapio);
	}

	// --------------------------------------------------------------------

	if(do_io) {
		static RRDSET *st_io = NULL;
		if(!st_io) {
			st_io = rrdset_create("system", "io", NULL, "disk", NULL, "Disk I/O", "kilobytes/s", 150, update_every, RRDSET_TYPE_AREA);

			rrddim_add(st_io, "in",  NULL,  1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st_io, "out", NULL, -1, 1, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st_io);

		rrddim_set(st_io, "in", pgpgin);
		rrddim_set(st_io, "out", pgpgout);
		rrdset_done(st_io);
	}

	// --------------------------------------------------------------------

	if(do_pgfaults) {
		static RRDSET *st_pgfaults = NULL;
		if(!st_pgfaults) {
			st_pgfaults = rrdset_create("mem", "pgfaults", NULL, "system", NULL, "Memory Page Faults", "page faults/s", 500, update_every, RRDSET_TYPE_LINE);
			st_pgfaults->isdetail = 1;

			rrddim_add(st_pgfaults, "minor",  NULL,  1, 1, RRDDIM_INCREMENTAL);
			rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRDDIM_INCREMENTAL);
		}
		else rrdset_next(st_pgfaults);

		rrddim_set(st_pgfaults, "minor", pgfault);
		rrddim_set(st_pgfaults, "major", pgmajfault);
		rrdset_done(st_pgfaults);
	}

	return 0;
}
コード例 #29
0
ファイル: proc_meminfo.c プロジェクト: 0-T-0/netdata
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;
}
コード例 #30
0
ファイル: proc_diskstats.c プロジェクト: rudijs/netdata
int do_proc_diskstats(int update_every, unsigned long long dt) {
	static procfile *ff = NULL;
	static char path_to_get_hw_sector_size[FILENAME_MAX + 1] = "";
	static int enable_new_disks = -1;
	static int do_io = -1, do_ops = -1, do_merged_ops = -1, do_iotime = -1, do_cur_ops = -1;

	if(enable_new_disks == -1)	enable_new_disks = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", 1);

	if(do_io == -1)			do_io 			= config_get_boolean("plugin:proc:/proc/diskstats", "bandwidth for all disks", 1);
	if(do_ops == -1)		do_ops 			= config_get_boolean("plugin:proc:/proc/diskstats", "operations for all disks", 1);
	if(do_merged_ops == -1)	do_merged_ops 	= config_get_boolean("plugin:proc:/proc/diskstats", "merged operations for all disks", 1);
	if(do_iotime == -1)		do_iotime 		= config_get_boolean("plugin:proc:/proc/diskstats", "i/o time for all disks", 1);
	if(do_cur_ops == -1)	do_cur_ops 		= config_get_boolean("plugin:proc:/proc/diskstats", "current operations for all disks", 1);

	if(dt) {};

	if(!ff) {
		char filename[FILENAME_MAX + 1];
		snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/diskstats");
		ff = procfile_open(config_get("plugin:proc:/proc/diskstats", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT);
	}
	if(!ff) return 1;

	if(!path_to_get_hw_sector_size[0]) {
		char filename[FILENAME_MAX + 1];
		snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/block/%s/queue/hw_sector_size");
		snprintf(path_to_get_hw_sector_size, FILENAME_MAX, "%s%s", global_host_prefix, config_get("plugin:proc:/proc/diskstats", "path to get h/w sector size", filename));
	}

	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;

	for(l = 0; l < lines ;l++) {
		char *disk;
		unsigned long long 	major = 0, minor = 0,
							reads = 0,  reads_merged = 0,  readsectors = 0,  readms = 0,
							writes = 0, writes_merged = 0, writesectors = 0, writems = 0,
							currentios = 0, iosms = 0, wiosms = 0;

		words = procfile_linewords(ff, l);
		if(words < 14) continue;

		major 			= strtoull(procfile_lineword(ff, l, 0), NULL, 10);
		minor 			= strtoull(procfile_lineword(ff, l, 1), NULL, 10);
		disk 			= procfile_lineword(ff, l, 2);
		reads 			= strtoull(procfile_lineword(ff, l, 3), NULL, 10);
		reads_merged 	= strtoull(procfile_lineword(ff, l, 4), NULL, 10);
		readsectors 	= strtoull(procfile_lineword(ff, l, 5), NULL, 10);
		readms 			= strtoull(procfile_lineword(ff, l, 6), NULL, 10);
		writes 			= strtoull(procfile_lineword(ff, l, 7), NULL, 10);
		writes_merged 	= strtoull(procfile_lineword(ff, l, 8), NULL, 10);
		writesectors 	= strtoull(procfile_lineword(ff, l, 9), NULL, 10);
		writems 		= strtoull(procfile_lineword(ff, l, 10), NULL, 10);
		currentios 		= strtoull(procfile_lineword(ff, l, 11), NULL, 10);
		iosms 			= strtoull(procfile_lineword(ff, l, 12), NULL, 10);
		wiosms 			= strtoull(procfile_lineword(ff, l, 13), NULL, 10);

		int def_enabled = 0;

		// remove slashes from disk names
		char *s;
		for(s = disk; *s ;s++) if(*s == '/') *s = '_';

		switch(major) {
			case 9: // MDs
			case 43: // network block
			case 144: // nfs
			case 145: // nfs
			case 146: // nfs
			case 199: // veritas
			case 201: // veritas
			case 251: // dm
				def_enabled = enable_new_disks;
				break;

			case 48: // RAID
			case 49: // RAID
			case 50: // RAID
			case 51: // RAID
			case 52: // RAID
			case 53: // RAID
			case 54: // RAID
			case 55: // RAID
			case 112: // RAID
			case 136: // RAID
			case 137: // RAID
			case 138: // RAID
			case 139: // RAID
			case 140: // RAID
			case 141: // RAID
			case 142: // RAID
			case 143: // RAID
			case 179: // MMC
			case 180: // USB
				if(minor % 8) def_enabled = 0; // partitions
				else def_enabled = enable_new_disks;
				break;

			case 8: // scsi disks
			case 65: // scsi disks
			case 66: // scsi disks
			case 67: // scsi disks
			case 68: // scsi disks
			case 69: // scsi disks
			case 70: // scsi disks
			case 71: // scsi disks
			case 72: // scsi disks
			case 73: // scsi disks
			case 74: // scsi disks
			case 75: // scsi disks
			case 76: // scsi disks
			case 77: // scsi disks
			case 78: // scsi disks
			case 79: // scsi disks
			case 80: // i2o
			case 81: // i2o
			case 82: // i2o
			case 83: // i2o
			case 84: // i2o
			case 85: // i2o
			case 86: // i2o
			case 87: // i2o
			case 101: // hyperdisk
			case 102: // compressed
			case 104: // scsi
			case 105: // scsi
			case 106: // scsi
			case 107: // scsi
			case 108: // scsi
			case 109: // scsi
			case 110: // scsi
			case 111: // scsi
			case 114: // bios raid
			case 116: // ram board
			case 128: // scsi
			case 129: // scsi
			case 130: // scsi
			case 131: // scsi
			case 132: // scsi
			case 133: // scsi
			case 134: // scsi
			case 135: // scsi
			case 153: // raid
			case 202: // xen
			case 256: // flash
			case 257: // flash
				if(minor % 16) def_enabled = 0; // partitions
				else def_enabled = enable_new_disks;
				break;

			case 160: // raid
			case 161: // raid
				if(minor % 32) def_enabled = 0; // partitions
				else def_enabled = enable_new_disks;
				break;

			case 3: // ide
			case 13: // 8bit ide
			case 22: // ide
			case 33: // ide
			case 34: // ide
			case 56: // ide
			case 57: // ide
			case 88: // ide
			case 89: // ide
			case 90: // ide
			case 91: // ide
				if(minor % 64) def_enabled = 0; // partitions
				else def_enabled = enable_new_disks;
				break;

			default:
				def_enabled = 0;
				break;
		}

		// check if it is enabled
		{
			char var_name[4096 + 1];
			snprintf(var_name, 4096, "disk %s", disk);
			if(!config_get_boolean("plugin:proc:/proc/diskstats", var_name, def_enabled)) continue;
		}

		RRDSET *st;

		// --------------------------------------------------------------------

		if(do_io) {
			st = rrdset_find_bytype(RRD_TYPE_DISK, disk);
			if(!st) {
				char tf[FILENAME_MAX + 1], *t;
				char ssfilename[FILENAME_MAX + 1];
				int sector_size = 512;

				strncpy(tf, disk, FILENAME_MAX);
				tf[FILENAME_MAX] = '\0';

				// replace all / with !
				while((t = strchr(tf, '/'))) *t = '!';

				snprintf(ssfilename, FILENAME_MAX, path_to_get_hw_sector_size, tf);
				FILE *fpss = fopen(ssfilename, "r");
				if(fpss) {
					char ssbuffer[1025];
					char *tmp = fgets(ssbuffer, 1024, fpss);

					if(tmp) {
						sector_size = atoi(tmp);
						if(sector_size <= 0) {
							error("Invalid sector size %d for device %s in %s. Assuming 512.", sector_size, disk, ssfilename);
							sector_size = 512;
						}
					}
					else error("Cannot read data for sector size for device %s from %s. Assuming 512.", disk, ssfilename);

					fclose(fpss);
				}
				else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);

				st = rrdset_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000, update_every, RRDSET_TYPE_AREA);

				rrddim_add(st, "reads", NULL, sector_size, 1024 * update_every, RRDDIM_INCREMENTAL);
				rrddim_add(st, "writes", NULL, sector_size * -1, 1024 * update_every, RRDDIM_INCREMENTAL);
			}
			else rrdset_next(st);

			rrddim_set(st, "reads", readsectors);
			rrddim_set(st, "writes", writesectors);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------

		if(do_ops) {
			st = rrdset_find_bytype("disk_ops", disk);
			if(!st) {
				st = rrdset_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001, update_every, RRDSET_TYPE_LINE);
				st->isdetail = 1;

				rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
				rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
			}
			else rrdset_next(st);

			rrddim_set(st, "reads", reads);
			rrddim_set(st, "writes", writes);
			rrdset_done(st);
		}
		
		// --------------------------------------------------------------------

		if(do_merged_ops) {
			st = rrdset_find_bytype("disk_merged_ops", disk);
			if(!st) {
				st = rrdset_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010, update_every, RRDSET_TYPE_LINE);
				st->isdetail = 1;

				rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
				rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
			}
			else rrdset_next(st);

			rrddim_set(st, "reads", reads_merged);
			rrddim_set(st, "writes", writes_merged);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------

		if(do_iotime) {
			st = rrdset_find_bytype("disk_iotime", disk);
			if(!st) {
				st = rrdset_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005, update_every, RRDSET_TYPE_LINE);
				st->isdetail = 1;

				rrddim_add(st, "reads", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
				rrddim_add(st, "writes", NULL, -1, 1 * update_every, RRDDIM_INCREMENTAL);
				rrddim_add(st, "latency", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
				rrddim_add(st, "weighted", NULL, 1, 1 * update_every, RRDDIM_INCREMENTAL);
			}
			else rrdset_next(st);

			rrddim_set(st, "reads", readms);
			rrddim_set(st, "writes", writems);
			rrddim_set(st, "latency", iosms);
			rrddim_set(st, "weighted", wiosms);
			rrdset_done(st);
		}

		// --------------------------------------------------------------------

		if(do_cur_ops) {
			st = rrdset_find_bytype("disk_cur_ops", disk);
			if(!st) {
				st = rrdset_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004, update_every, RRDSET_TYPE_LINE);
				st->isdetail = 1;

				rrddim_add(st, "operations", NULL, 1, 1, RRDDIM_ABSOLUTE);
			}
			else rrdset_next(st);

			rrddim_set(st, "operations", currentios);
			rrdset_done(st);
		}
	}
	
	return 0;
}