int do_proc_sys_kernel_random_entropy_avail(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/sys/kernel/random/entropy_avail"); ff = procfile_open(config_get("plugin:proc:/proc/sys/kernel/random/entropy_avail", "filename to monitor", filename), "", 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 unsigned long long entropy = str2ull(procfile_lineword(ff, 0, 0)); RRDSET *st = rrdset_find_bytype("system", "entropy"); if(unlikely(!st)) { st = rrdset_create("system", "entropy", NULL, "entropy", NULL, "Available Entropy", "entropy", 1000, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "entropy", NULL, 1, 1, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "entropy", entropy); rrdset_done(st); return 0; }
static inline unsigned long long ensurenum(char *s, unsigned long long *n, int b) { unsigned long long temp; enum errorcodes status; char tmp[25]; /* if the user doesn't provide his variable two change, create a temporary one */ if (!n) n = &temp; status = str2ull(s, n, b); /* generate a message to indicate required base if `b` is not 0 [any base]. */ if (b) snprintf(tmp, 25, "Base %d is required.", b); switch (status) { case FAILURE: case INCOMPLETE: _throwerror(1, "%s is not a valid number.%s", s, b ? tmp : ""); case OVERFLOW: _throwerror(1, "%s is a too large number.", s); } return *n; }
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; }
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; } } } }
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; }
int do_sys_class_power_supply(int update_every, usec_t dt) { (void)dt; static int do_capacity = -1, do_property[3] = {-1}; static int keep_fds_open = CONFIG_BOOLEAN_NO, keep_fds_open_config = -1; static char *dirname = NULL; if(unlikely(do_capacity == -1)) { do_capacity = config_get_boolean("plugin:proc:/sys/class/power_supply", "battery capacity", CONFIG_BOOLEAN_YES); do_property[0] = config_get_boolean("plugin:proc:/sys/class/power_supply", "battery charge", CONFIG_BOOLEAN_NO); do_property[1] = config_get_boolean("plugin:proc:/sys/class/power_supply", "battery energy", CONFIG_BOOLEAN_NO); do_property[2] = config_get_boolean("plugin:proc:/sys/class/power_supply", "power supply voltage", CONFIG_BOOLEAN_NO); keep_fds_open_config = config_get_boolean_ondemand("plugin:proc:/sys/class/power_supply", "keep files open", CONFIG_BOOLEAN_AUTO); char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/sys/class/power_supply"); dirname = config_get("plugin:proc:/sys/class/power_supply", "directory to monitor", filename); } DIR *dir = opendir(dirname); if(unlikely(!dir)) { error("Cannot read directory '%s'", dirname); return 1; } struct dirent *de = NULL; while(likely(de = readdir(dir))) { if(likely(de->d_type == DT_DIR && ( (de->d_name[0] == '.' && de->d_name[1] == '\0') || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') ))) continue; if(likely(de->d_type == DT_LNK || de->d_type == DT_DIR)) { uint32_t hash = simple_hash(de->d_name); struct power_supply *ps; for(ps = power_supply_root; ps; ps = ps->next) { if(unlikely(ps->hash == hash && !strcmp(ps->name, de->d_name))) { ps->found = 1; break; } } // allocate memory for power supply and initialize it if(unlikely(!ps)) { ps = callocz(sizeof(struct power_supply), 1); ps->name = strdupz(de->d_name); ps->hash = simple_hash(de->d_name); ps->found = 1; ps->next = power_supply_root; power_supply_root = ps; struct stat stbuf; if(likely(do_capacity != CONFIG_BOOLEAN_NO)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/%s/%s", dirname, de->d_name, "capacity"); if (stat(filename, &stbuf) == 0) { ps->capacity = callocz(sizeof(struct capacity), 1); ps->capacity->filename = strdupz(filename); ps->capacity->fd = -1; files_num++; } } // allocate memory and initialize structures for every property and file found size_t pr_idx, pd_idx; size_t prev_idx = 3; // there is no property with this index for(pr_idx = 0; pr_idx < 3; pr_idx++) { if(unlikely(do_property[pr_idx] != CONFIG_BOOLEAN_NO)) { struct ps_property *pr = NULL; for(pd_idx = pr_idx * 5; pd_idx < pr_idx * 5 + 5; pd_idx++) { // check if file exists char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/%s/%s_%s", dirname, de->d_name, ps_property_names[pr_idx], ps_property_dim_names[pd_idx]); if (stat(filename, &stbuf) == 0) { // add chart if(unlikely(prev_idx != pr_idx)) { pr = callocz(sizeof(struct ps_property), 1); pr->name = strdupz(ps_property_names[pr_idx]); pr->title = strdupz(ps_property_titles[pr_idx]); pr->units = strdupz(ps_property_units[pr_idx]); prev_idx = pr_idx; pr->next = ps->property_root; ps->property_root = pr; } // add dimension struct ps_property_dim *pd; pd= callocz(sizeof(struct ps_property_dim), 1); pd->name = strdupz(ps_property_dim_names[pd_idx]); pd->filename = strdupz(filename); pd->fd = -1; files_num++; pd->next = pr->property_dim_root; pr->property_dim_root = pd; } } } } } // read capacity file if(likely(ps->capacity)) { char buffer[30 + 1]; if(unlikely(ps->capacity->fd == -1)) { ps->capacity->fd = open(ps->capacity->filename, O_RDONLY, 0666); if(unlikely(ps->capacity->fd == -1)) { error("Cannot open file '%s'", ps->capacity->filename); power_supply_free(ps); } } ssize_t r = read(ps->capacity->fd, buffer, 30); if(unlikely(r < 1)) { error("Cannot read file '%s'", ps->capacity->filename); power_supply_free(ps); } else { buffer[r] = '\0'; ps->capacity->value = str2ull(buffer); } if(unlikely(!keep_fds_open)) { close(ps->capacity->fd); ps->capacity->fd = -1; } else if(unlikely(lseek(ps->capacity->fd, 0, SEEK_SET) == -1)) { error("Cannot seek in file '%s'", ps->capacity->filename); close(ps->capacity->fd); ps->capacity->fd = -1; } } // read property files int read_error = 0; struct ps_property *pr; for(pr = ps->property_root; pr && !read_error; pr = pr->next) { struct ps_property_dim *pd; for(pd = pr->property_dim_root; pd; pd = pd->next) { char buffer[30 + 1]; if(unlikely(pd->fd == -1)) { pd->fd = open(pd->filename, O_RDONLY, 0666); if(unlikely(pd->fd == -1)) { error("Cannot open file '%s'", pd->filename); read_error = 1; power_supply_free(ps); break; } } ssize_t r = read(pd->fd, buffer, 30); if(unlikely(r < 1)) { error("Cannot read file '%s'", pd->filename); read_error = 1; power_supply_free(ps); break; } buffer[r] = '\0'; pd->value = str2ull(buffer); if(unlikely(!keep_fds_open)) { close(pd->fd); pd->fd = -1; } else if(unlikely(lseek(pd->fd, 0, SEEK_SET) == -1)) { error("Cannot seek in file '%s'", pd->filename); close(pd->fd); pd->fd = -1; } } } } } closedir(dir); keep_fds_open = keep_fds_open_config; if(likely(keep_fds_open_config == CONFIG_BOOLEAN_AUTO)) { if(unlikely(files_num > 32)) keep_fds_open = CONFIG_BOOLEAN_NO; else keep_fds_open = CONFIG_BOOLEAN_YES; } // -------------------------------------------------------------------- struct power_supply *ps = power_supply_root; while(unlikely(ps)) { if(unlikely(!ps->found)) { struct power_supply *f = ps; ps = ps->next; power_supply_free(f); continue; } if(likely(ps->capacity)) { if(unlikely(!ps->capacity->st)) { ps->capacity->st = rrdset_create_localhost( "powersupply_capacity" , ps->name , NULL , ps->name , "powersupply.capacity" , "Battery capacity" , "percentage" , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_POWER_SUPPLY_NAME , NETDATA_CHART_PRIO_POWER_SUPPLY_CAPACITY , update_every , RRDSET_TYPE_LINE ); } else rrdset_next(ps->capacity->st); if(unlikely(!ps->capacity->rd)) ps->capacity->rd = rrddim_add(ps->capacity->st, "capacity", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(ps->capacity->st, ps->capacity->rd, ps->capacity->value); rrdset_done(ps->capacity->st); } struct ps_property *pr; for(pr = ps->property_root; pr; pr = pr->next) { if(unlikely(!pr->st)) { char id[RRD_ID_LENGTH_MAX + 1], context[RRD_ID_LENGTH_MAX + 1]; snprintfz(id, RRD_ID_LENGTH_MAX, "powersupply_%s", pr->name); snprintfz(context, RRD_ID_LENGTH_MAX, "powersupply.%s", pr->name); pr->st = rrdset_create_localhost( id , ps->name , NULL , ps->name , context , pr->title , pr->units , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_POWER_SUPPLY_NAME , NETDATA_CHART_PRIO_POWER_SUPPLY_CAPACITY , update_every , RRDSET_TYPE_LINE ); } else rrdset_next(pr->st); struct ps_property_dim *pd; for(pd = pr->property_dim_root; pd; pd = pd->next) { if(unlikely(!pd->rd)) pd->rd = rrddim_add(pr->st, pd->name, NULL, 1, 1000000, RRD_ALGORITHM_ABSOLUTE); rrddim_set_by_pointer(pr->st, pd->rd, pd->value); } rrdset_done(pr->st); } ps->found = 0; ps = ps->next; } return 0; }
int do_proc_net_rpc_nfs(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; static int do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1; static int proc2_warning = 0, proc3_warning = 0, proc4_warning = 0; if(!ff) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/rpc/nfs"); ff = procfile_open(config_get("plugin:proc:/proc/net/rpc/nfs", "filename to monitor", filename), " \t", PROCFILE_FLAG_DEFAULT); } if(!ff) return 1; ff = procfile_readall(ff); if(!ff) return 0; // we return 0, so that we will retry to open it next time if(do_net == -1) do_net = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "network", 1); if(do_rpc == -1) do_rpc = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "rpc", 1); if(do_proc2 == -1) do_proc2 = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "NFS v2 procedures", 1); if(do_proc3 == -1) do_proc3 = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "NFS v3 procedures", 1); if(do_proc4 == -1) do_proc4 = config_get_boolean("plugin:proc:/proc/net/rpc/nfs", "NFS v4 procedures", 1); // if they are enabled, reset them to 1 // later we do them =2 to avoid doing strcmp() for all lines if(do_net) do_net = 1; if(do_rpc) do_rpc = 1; if(do_proc2) do_proc2 = 1; if(do_proc3) do_proc3 = 1; if(do_proc4) do_proc4 = 1; size_t lines = procfile_lines(ff), l; char *type; unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0; unsigned long long rpc_calls = 0, rpc_retransmits = 0, rpc_auth_refresh = 0; for(l = 0; l < lines ;l++) { size_t words = procfile_linewords(ff, l); if(!words) continue; type = procfile_lineword(ff, l, 0); if(do_net == 1 && strcmp(type, "net") == 0) { if(words < 5) { error("%s line of /proc/net/rpc/nfs has %zu words, expected %d", type, words, 5); continue; } net_count = str2ull(procfile_lineword(ff, l, 1)); net_udp_count = str2ull(procfile_lineword(ff, l, 2)); net_tcp_count = str2ull(procfile_lineword(ff, l, 3)); net_tcp_connections = str2ull(procfile_lineword(ff, l, 4)); unsigned long long sum = net_count + net_udp_count + net_tcp_count + net_tcp_connections; if(sum == 0ULL) do_net = -1; else do_net = 2; } else if(do_rpc == 1 && strcmp(type, "rpc") == 0) { if(words < 4) { error("%s line of /proc/net/rpc/nfs has %zu words, expected %d", type, words, 6); continue; } rpc_calls = str2ull(procfile_lineword(ff, l, 1)); rpc_retransmits = str2ull(procfile_lineword(ff, l, 2)); rpc_auth_refresh = str2ull(procfile_lineword(ff, l, 3)); unsigned long long sum = rpc_calls + rpc_retransmits + rpc_auth_refresh; if(sum == 0ULL) do_rpc = -1; else do_rpc = 2; } else if(do_proc2 == 1 && strcmp(type, "proc2") == 0) { // the first number is the count of numbers present // so we start for word 2 unsigned long long sum = 0; unsigned int i, j; for(i = 0, j = 2; j < words && nfs_proc2_values[i].name[0] ; i++, j++) { nfs_proc2_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfs_proc2_values[i].present = 1; sum += nfs_proc2_values[i].value; } if(sum == 0ULL) { if(!proc2_warning) { error("Disabling /proc/net/rpc/nfs v2 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it."); proc2_warning = 1; } do_proc2 = 0; } else do_proc2 = 2; } else if(do_proc3 == 1 && strcmp(type, "proc3") == 0) { // the first number is the count of numbers present // so we start for word 2 unsigned long long sum = 0; unsigned int i, j; for(i = 0, j = 2; j < words && nfs_proc3_values[i].name[0] ; i++, j++) { nfs_proc3_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfs_proc3_values[i].present = 1; sum += nfs_proc3_values[i].value; } if(sum == 0ULL) { if(!proc3_warning) { info("Disabling /proc/net/rpc/nfs v3 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it."); proc3_warning = 1; } do_proc3 = 0; } else do_proc3 = 2; } else if(do_proc4 == 1 && strcmp(type, "proc4") == 0) { // the first number is the count of numbers present // so we start for word 2 unsigned long long sum = 0; unsigned int i, j; for(i = 0, j = 2; j < words && nfs_proc4_values[i].name[0] ; i++, j++) { nfs_proc4_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfs_proc4_values[i].present = 1; sum += nfs_proc4_values[i].value; } if(sum == 0ULL) { if(!proc4_warning) { info("Disabling /proc/net/rpc/nfs v4 procedure calls chart. It seems unused on this machine. It will be enabled automatically when found with data in it."); proc4_warning = 1; } do_proc4 = 0; } else do_proc4 = 2; } } // -------------------------------------------------------------------- if(do_net == 2) { static RRDSET *st = NULL; static RRDDIM *rd_udp = NULL, *rd_tcp = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "net" , NULL , "network" , NULL , "NFS Client Network" , "operations/s" , "proc" , "net/rpc/nfs" , 2207 , update_every , RRDSET_TYPE_STACKED ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rd_udp = rrddim_add(st, "udp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_tcp = rrddim_add(st, "tcp", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); // ignore net_count, net_tcp_connections (void)net_count; (void)net_tcp_connections; rrddim_set_by_pointer(st, rd_udp, net_udp_count); rrddim_set_by_pointer(st, rd_tcp, net_tcp_count); rrdset_done(st); } // -------------------------------------------------------------------- if(do_rpc == 2) { static RRDSET *st = NULL; static RRDDIM *rd_calls = NULL, *rd_retransmits = NULL, *rd_auth_refresh = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "rpc" , NULL , "rpc" , NULL , "NFS Client Remote Procedure Calls Statistics" , "calls/s" , "proc" , "net/rpc/nfs" , 2208 , update_every , RRDSET_TYPE_LINE ); rrdset_flag_set(st, RRDSET_FLAG_DETAIL); rd_calls = rrddim_add(st, "calls", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_retransmits = rrddim_add(st, "retransmits", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); rd_auth_refresh = rrddim_add(st, "auth_refresh", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set_by_pointer(st, rd_calls, rpc_calls); rrddim_set_by_pointer(st, rd_retransmits, rpc_retransmits); rrddim_set_by_pointer(st, rd_auth_refresh, rpc_auth_refresh); rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc2 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "proc2" , NULL , "nfsv2rpc" , NULL , "NFS v2 Client Remote Procedure Calls" , "calls/s" , "proc" , "net/rpc/nfs" , 2209 , update_every , RRDSET_TYPE_STACKED ); } else rrdset_next(st); size_t i; for(i = 0; nfs_proc2_values[i].present ; i++) { if(unlikely(!nfs_proc2_values[i].rd)) nfs_proc2_values[i].rd = rrddim_add(st, nfs_proc2_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st, nfs_proc2_values[i].rd, nfs_proc2_values[i].value); } rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc3 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "proc3" , NULL , "nfsv3rpc" , NULL , "NFS v3 Client Remote Procedure Calls" , "calls/s" , "proc" , "net/rpc/nfs" , 2210 , update_every , RRDSET_TYPE_STACKED ); } else rrdset_next(st); size_t i; for(i = 0; nfs_proc3_values[i].present ; i++) { if(unlikely(!nfs_proc3_values[i].rd)) nfs_proc3_values[i].rd = rrddim_add(st, nfs_proc3_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st, nfs_proc3_values[i].rd, nfs_proc3_values[i].value); } rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc4 == 2) { static RRDSET *st = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "nfs" , "proc4" , NULL , "nfsv4rpc" , NULL , "NFS v4 Client Remote Procedure Calls" , "calls/s" , "proc" , "net/rpc/nfs" , 2211 , update_every , RRDSET_TYPE_STACKED ); } else rrdset_next(st); size_t i; for(i = 0; nfs_proc4_values[i].present ; i++) { if(unlikely(!nfs_proc4_values[i].rd)) nfs_proc4_values[i].rd = rrddim_add(st, nfs_proc4_values[i].name, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rrddim_set_by_pointer(st, nfs_proc4_values[i].rd, nfs_proc4_values[i].value); } rrdset_done(st); } return 0; }
int 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; }
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", netdata_configured_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 size_t lines = procfile_lines(ff), l; size_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; size_t idlen = strlen(irr->id); if(unlikely(idlen && irr->id[idlen - 1] == ':')) irr->id[idlen - 1] = '\0'; int c; for(c = 0; c < cpus ;c++) { if(likely((c + 1) < (int)words)) 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; } if(unlikely(isdigit(irr->id[0]) && (uint32_t)(cpus + 2) < words)) { strncpyz(irr->name, procfile_lineword(ff, l, words - 1), MAX_INTERRUPT_NAME); size_t nlen = strlen(irr->name); idlen = strlen(irr->id); if(likely(nlen + 1 + idlen <= MAX_INTERRUPT_NAME)) { irr->name[nlen] = '_'; strncpyz(&irr->name[nlen + 1], irr->id, MAX_INTERRUPT_NAME - nlen - 1); } 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; } // -------------------------------------------------------------------- static RRDSET *st_system_interrupts = NULL; if(unlikely(!st_system_interrupts)) st_system_interrupts = rrdset_create_localhost( "system" , "interrupts" , NULL , "interrupts" , NULL , "System interrupts" , "interrupts/s" , 1000 , update_every , RRDSET_TYPE_STACKED ); else rrdset_next(st_system_interrupts); for(l = 0; l < lines ;l++) { struct interrupt *irr = irrindex(irrs, l, cpus); if(unlikely(!irr->used)) continue; // some interrupt may have changed without changing the total number of lines // if the same number of interrupts have been added and removed between two // calls of this function. if(unlikely(!irr->rd || strncmp(irr->rd->name, irr->name, MAX_INTERRUPT_NAME) != 0)) { irr->rd = rrddim_find(st_system_interrupts, irr->id); if(unlikely(!irr->rd)) irr->rd = rrddim_add(st_system_interrupts, irr->id, irr->name, 1, 1, RRD_ALGORITHM_INCREMENTAL); else rrddim_set_name(st_system_interrupts, irr->rd, irr->name); // also reset per cpu RRDDIMs to avoid repeating strncmp() in the per core loop if(likely(do_per_core)) { int c; for (c = 0; c < cpus ;c++) irr->cpu[c].rd = NULL; } } rrddim_set_by_pointer(st_system_interrupts, irr->rd, irr->total); } rrdset_done(st_system_interrupts); // -------------------------------------------------------------------- if(likely(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])) { char id[50+1]; snprintfz(id, 50, "cpu%d_interrupts", c); char title[100+1]; snprintfz(title, 100, "CPU%d Interrupts", c); core_st[c] = rrdset_create_localhost( "cpu" , id , NULL , "interrupts" , "cpu.interrupts" , title , "interrupts/s" , 1100 + 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; }
HRESULT CALLBACK pe(PDEBUG_CLIENT4 Client, PCSTR args) { INIT_API(); ULONG_PTR ulAddress = 0; ULONG_PTR ulBase = 0; ULONG_PTR ulImageSize = 0; HRESULT result = S_OK; ULONG ulSetionCount = 0; BOOL bAllPrint = TRUE; BOOL bPrintDosHeard = FALSE; BOOL bPrintNtHeard = FALSE; BOOL bSection = FALSE; BOOL bImport = FALSE; BOOL bExport = FALSE; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES] = { 0 }; if ( args == NULL) { result = S_FALSE; goto ex; }do { const char * split = " "; char * p = NULL, *params = NULL, *next = NULL; params = new char[strlen(args) + 1]; if (params == NULL) { result = S_FALSE; goto ex; } _try { memset(params, 0, strlen(args) + 1); strcpy_s(params, strlen(args) + 1, args); p = strtok_s(params, split, &next); while (p != NULL) { if (_stricmp(p, "-section") == 0) { bAllPrint = FALSE; bSection = TRUE; } else if (_stricmp(p, "-dos") == 0) { bAllPrint = FALSE; bPrintDosHeard = TRUE; } else if (_stricmp(p, "-nt") == 0) { bAllPrint = FALSE; bPrintNtHeard = TRUE; } else if (_stricmp(p, "-import") == 0) { bAllPrint = FALSE; bImport = TRUE; } else if (_stricmp(p, "-export") == 0) { bAllPrint = FALSE; bExport = TRUE; } else if (p) { char *endptr = NULL; ulAddress = str2ull(p, &endptr, 16); ulBase = ulAddress; } p = strtok_s(NULL, split, &next); } }_finally { if (params) { delete[]params; params = NULL; } } } while (FALSE); if (ulAddress == 0) { result = S_FALSE; goto ex; } if (result = PE_PrintDosHeard(&ulAddress, bAllPrint | bPrintDosHeard) != S_OK) { goto ex; } if (result = PE_PrintNtHeard(&ulAddress, bAllPrint | bPrintNtHeard, &ulSetionCount, DataDirectory, &ulImageSize) != S_OK) { goto ex; } if (result = PE_PrintSection(&ulAddress, ulSetionCount, bAllPrint | bSection) != S_OK) { goto ex; } PBYTE pImage = new BYTE[ulImageSize]; if (pImage == NULL) { result = S_FALSE; goto ex; } _try { ULONG ulReadSize = 0; memset(pImage, 0, ulImageSize); result = g_ExtDataSpaces->ReadVirtual(ulBase, pImage, ulImageSize, &ulReadSize); if (result != S_OK) { dprintf("读取虚拟地址 %x 错误 \n", ulBase); goto ex; } if (ulReadSize != ulImageSize) { dprintf("读取数据长度错误。 \n"); result = S_FALSE; goto ex; } if (result = PE_PrintImport(pImage, DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT], bAllPrint | bImport) != S_OK) { goto ex; } if (result = PE_PrintExport(pImage, DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT], ulBase, bAllPrint | bExport) != S_OK) { goto ex; } }_finally { if (pImage) { delete[]pImage; pImage = NULL; } } ex: EXIT_API(); return result; }
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; }
static int read_per_core_time_in_state_files(struct cpu_chart *all_cpu_charts, size_t len, size_t index) { size_t x, files_read = 0, files_nonzero = 0; for(x = 0; x < len ; x++) { struct per_core_single_number_file *f = &all_cpu_charts[x].files[index]; struct per_core_time_in_state_file *tsf = &all_cpu_charts[x].time_in_state_files; f->found = 0; if(unlikely(!tsf->filename)) continue; if(unlikely(!tsf->ff)) { tsf->ff = procfile_open(tsf->filename, " \t:", PROCFILE_FLAG_DEFAULT); if(unlikely(!tsf->ff)) { error("Cannot open file '%s'", tsf->filename); continue; } } tsf->ff = procfile_readall(tsf->ff); if(unlikely(!tsf->ff)) { error("Cannot read file '%s'", tsf->filename); procfile_close(tsf->ff); tsf->ff = NULL; continue; } else { // successful read size_t lines = procfile_lines(tsf->ff), l; size_t words; unsigned long long total_ticks_since_last = 0, avg_freq = 0; // Check if there is at least one frequency in time_in_state if (procfile_word(tsf->ff, 0)[0] == '\0') { if(unlikely(keep_per_core_fds_open != CONFIG_BOOLEAN_YES)) { procfile_close(tsf->ff); tsf->ff = NULL; } // TODO: Is there a better way to avoid spikes than calculating the average over // the whole period under schedutil governor? // freez(tsf->last_ticks); // tsf->last_ticks = NULL; // tsf->last_ticks_len = 0; continue; } if (unlikely(tsf->last_ticks_len < lines || tsf->last_ticks == NULL)) { tsf->last_ticks = reallocz(tsf->last_ticks, sizeof(struct last_ticks) * lines); memset(tsf->last_ticks, 0, sizeof(struct last_ticks) * lines); tsf->last_ticks_len = lines; } f->value = 0; for(l = 0; l < lines - 1 ;l++) { unsigned long long frequency = 0, ticks = 0, ticks_since_last = 0; words = procfile_linewords(tsf->ff, l); if(unlikely(words < 2)) { error("Cannot read time_in_state line. Expected 2 params, read %zu.", words); continue; } frequency = str2ull(procfile_lineword(tsf->ff, l, 0)); ticks = str2ull(procfile_lineword(tsf->ff, l, 1)); // It is assumed that frequencies are static and sorted ticks_since_last = ticks - tsf->last_ticks[l].ticks; tsf->last_ticks[l].frequency = frequency; tsf->last_ticks[l].ticks = ticks; total_ticks_since_last += ticks_since_last; avg_freq += frequency * ticks_since_last; } if (likely(total_ticks_since_last)) { avg_freq /= total_ticks_since_last; f->value = avg_freq; } if(unlikely(keep_per_core_fds_open != CONFIG_BOOLEAN_YES)) { procfile_close(tsf->ff); tsf->ff = NULL; } } files_read++; f->found = 1; if(likely(f->value != 0)) files_nonzero++; } if(unlikely(files_read == 0)) return -1; if(unlikely(files_nonzero == 0)) return 0; return (int)files_nonzero; }
int do_proc_net_rpc_nfsd(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; static int do_rc = -1, do_fh = -1, do_io = -1, do_th = -1, do_ra = -1, do_net = -1, do_rpc = -1, do_proc2 = -1, do_proc3 = -1, do_proc4 = -1, do_proc4ops = -1; static int ra_warning = 0, th_warning = 0, proc2_warning = 0, proc3_warning = 0, proc4_warning = 0, proc4ops_warning = 0; if(!ff) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/rpc/nfsd"); ff = procfile_open(config_get("plugin:proc:/proc/net/rpc/nfsd", "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_rc == -1) do_rc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read cache", 1); if(do_fh == -1) do_fh = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "file handles", 1); if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "I/O", 1); if(do_th == -1) do_th = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "threads", 1); if(do_ra == -1) do_ra = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "read ahead", 1); if(do_net == -1) do_net = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "network", 1); if(do_rpc == -1) do_rpc = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "rpc", 1); if(do_proc2 == -1) do_proc2 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v2 procedures", 1); if(do_proc3 == -1) do_proc3 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v3 procedures", 1); if(do_proc4 == -1) do_proc4 = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 procedures", 1); if(do_proc4ops == -1) do_proc4ops = config_get_boolean("plugin:proc:/proc/net/rpc/nfsd", "NFS v4 operations", 1); // if they are enabled, reset them to 1 // later we do them =2 to avoid doing strcmp() for all lines if(do_rc) do_rc = 1; if(do_fh) do_fh = 1; if(do_io) do_io = 1; if(do_th) do_th = 1; if(do_ra) do_ra = 1; if(do_net) do_net = 1; if(do_rpc) do_rpc = 1; if(do_proc2) do_proc2 = 1; if(do_proc3) do_proc3 = 1; if(do_proc4) do_proc4 = 1; if(do_proc4ops) do_proc4ops = 1; size_t lines = procfile_lines(ff), l; char *type; unsigned long long rc_hits = 0, rc_misses = 0, rc_nocache = 0; unsigned long long fh_stale = 0, fh_total_lookups = 0, fh_anonymous_lookups = 0, fh_dir_not_in_dcache = 0, fh_non_dir_not_in_dcache = 0; unsigned long long io_read = 0, io_write = 0; unsigned long long th_threads = 0, th_fullcnt = 0, th_hist10 = 0, th_hist20 = 0, th_hist30 = 0, th_hist40 = 0, th_hist50 = 0, th_hist60 = 0, th_hist70 = 0, th_hist80 = 0, th_hist90 = 0, th_hist100 = 0; unsigned long long ra_size = 0, ra_hist10 = 0, ra_hist20 = 0, ra_hist30 = 0, ra_hist40 = 0, ra_hist50 = 0, ra_hist60 = 0, ra_hist70 = 0, ra_hist80 = 0, ra_hist90 = 0, ra_hist100 = 0, ra_none = 0; unsigned long long net_count = 0, net_udp_count = 0, net_tcp_count = 0, net_tcp_connections = 0; unsigned long long rpc_calls = 0, rpc_bad_format = 0, rpc_bad_auth = 0, rpc_bad_client = 0; for(l = 0; l < lines ;l++) { size_t words = procfile_linewords(ff, l); if(!words) continue; type = procfile_lineword(ff, l, 0); if(do_rc == 1 && strcmp(type, "rc") == 0) { if(words < 4) { error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 4); continue; } rc_hits = str2ull(procfile_lineword(ff, l, 1)); rc_misses = str2ull(procfile_lineword(ff, l, 2)); rc_nocache = str2ull(procfile_lineword(ff, l, 3)); unsigned long long sum = rc_hits + rc_misses + rc_nocache; if(sum == 0ULL) do_rc = -1; else do_rc = 2; } else if(do_fh == 1 && strcmp(type, "fh") == 0) { if(words < 6) { error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 6); continue; } fh_stale = str2ull(procfile_lineword(ff, l, 1)); fh_total_lookups = str2ull(procfile_lineword(ff, l, 2)); fh_anonymous_lookups = str2ull(procfile_lineword(ff, l, 3)); fh_dir_not_in_dcache = str2ull(procfile_lineword(ff, l, 4)); fh_non_dir_not_in_dcache = str2ull(procfile_lineword(ff, l, 5)); unsigned long long sum = fh_stale + fh_total_lookups + fh_anonymous_lookups + fh_dir_not_in_dcache + fh_non_dir_not_in_dcache; if(sum == 0ULL) do_fh = -1; else do_fh = 2; } else if(do_io == 1 && strcmp(type, "io") == 0) { if(words < 3) { error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 3); continue; } io_read = str2ull(procfile_lineword(ff, l, 1)); io_write = str2ull(procfile_lineword(ff, l, 2)); unsigned long long sum = io_read + io_write; if(sum == 0ULL) do_io = -1; else do_io = 2; } else if(do_th == 1 && strcmp(type, "th") == 0) { if(words < 13) { error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 13); continue; } th_threads = str2ull(procfile_lineword(ff, l, 1)); th_fullcnt = str2ull(procfile_lineword(ff, l, 2)); th_hist10 = (unsigned long long)(atof(procfile_lineword(ff, l, 3)) * 1000.0); th_hist20 = (unsigned long long)(atof(procfile_lineword(ff, l, 4)) * 1000.0); th_hist30 = (unsigned long long)(atof(procfile_lineword(ff, l, 5)) * 1000.0); th_hist40 = (unsigned long long)(atof(procfile_lineword(ff, l, 6)) * 1000.0); th_hist50 = (unsigned long long)(atof(procfile_lineword(ff, l, 7)) * 1000.0); th_hist60 = (unsigned long long)(atof(procfile_lineword(ff, l, 8)) * 1000.0); th_hist70 = (unsigned long long)(atof(procfile_lineword(ff, l, 9)) * 1000.0); th_hist80 = (unsigned long long)(atof(procfile_lineword(ff, l, 10)) * 1000.0); th_hist90 = (unsigned long long)(atof(procfile_lineword(ff, l, 11)) * 1000.0); th_hist100 = (unsigned long long)(atof(procfile_lineword(ff, l, 12)) * 1000.0); // threads histogram has been disabled on recent kernels // http://permalink.gmane.org/gmane.linux.nfs/24528 unsigned long long sum = th_hist10 + th_hist20 + th_hist30 + th_hist40 + th_hist50 + th_hist60 + th_hist70 + th_hist80 + th_hist90 + th_hist100; if(sum == 0ULL) { if(!th_warning) { info("Disabling /proc/net/rpc/nfsd threads histogram. It seems unused on this machine. It will be enabled automatically when found with data in it."); th_warning = 1; } do_th = -1; } else do_th = 2; } else if(do_ra == 1 && strcmp(type, "ra") == 0) { if(words < 13) { error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 13); continue; } ra_size = str2ull(procfile_lineword(ff, l, 1)); ra_hist10 = str2ull(procfile_lineword(ff, l, 2)); ra_hist20 = str2ull(procfile_lineword(ff, l, 3)); ra_hist30 = str2ull(procfile_lineword(ff, l, 4)); ra_hist40 = str2ull(procfile_lineword(ff, l, 5)); ra_hist50 = str2ull(procfile_lineword(ff, l, 6)); ra_hist60 = str2ull(procfile_lineword(ff, l, 7)); ra_hist70 = str2ull(procfile_lineword(ff, l, 8)); ra_hist80 = str2ull(procfile_lineword(ff, l, 9)); ra_hist90 = str2ull(procfile_lineword(ff, l, 10)); ra_hist100 = str2ull(procfile_lineword(ff, l, 11)); ra_none = str2ull(procfile_lineword(ff, l, 12)); unsigned long long sum = ra_hist10 + ra_hist20 + ra_hist30 + ra_hist40 + ra_hist50 + ra_hist60 + ra_hist70 + ra_hist80 + ra_hist90 + ra_hist100 + ra_none; if(sum == 0ULL) { if(!ra_warning) { info("Disabling /proc/net/rpc/nfsd read ahead histogram. It seems unused on this machine. It will be enabled automatically when found with data in it."); ra_warning = 1; } do_ra = -1; } else do_ra = 2; } else if(do_net == 1 && strcmp(type, "net") == 0) { if(words < 5) { error("%s line of /proc/net/rpc/nfsd 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 < 6) { error("%s line of /proc/net/rpc/nfsd has %zu words, expected %d", type, words, 6); continue; } rpc_calls = str2ull(procfile_lineword(ff, l, 1)); rpc_bad_format = str2ull(procfile_lineword(ff, l, 2)); rpc_bad_auth = str2ull(procfile_lineword(ff, l, 3)); rpc_bad_client = str2ull(procfile_lineword(ff, l, 4)); unsigned long long sum = rpc_calls + rpc_bad_format + rpc_bad_auth + rpc_bad_client; 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 && nfsd_proc2_values[i].name[0] ; i++, j++) { nfsd_proc2_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfsd_proc2_values[i].present = 1; sum += nfsd_proc2_values[i].value; } if(sum == 0ULL) { if(!proc2_warning) { error("Disabling /proc/net/rpc/nfsd 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 && nfsd_proc3_values[i].name[0] ; i++, j++) { nfsd_proc3_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfsd_proc3_values[i].present = 1; sum += nfsd_proc3_values[i].value; } if(sum == 0ULL) { if(!proc3_warning) { info("Disabling /proc/net/rpc/nfsd 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 && nfsd_proc4_values[i].name[0] ; i++, j++) { nfsd_proc4_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfsd_proc4_values[i].present = 1; sum += nfsd_proc4_values[i].value; } if(sum == 0ULL) { if(!proc4_warning) { info("Disabling /proc/net/rpc/nfsd 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; } else if(do_proc4ops == 1 && strcmp(type, "proc4ops") == 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 && nfsd4_ops_values[i].name[0] ; i++, j++) { nfsd4_ops_values[i].value = str2ull(procfile_lineword(ff, l, j)); nfsd4_ops_values[i].present = 1; sum += nfsd4_ops_values[i].value; } if(sum == 0ULL) { if(!proc4ops_warning) { info("Disabling /proc/net/rpc/nfsd v4 operations chart. It seems unused on this machine. It will be enabled automatically when found with data in it."); proc4ops_warning = 1; } do_proc4ops = 0; } else do_proc4ops = 2; } } RRDSET *st; // -------------------------------------------------------------------- if(do_rc == 2) { st = rrdset_find_bytype("nfsd", "readcache"); if(!st) { st = rrdset_create("nfsd", "readcache", NULL, "cache", NULL, "NFS Server Read Cache", "reads/s", 5000, update_every, RRDSET_TYPE_STACKED); rrddim_add(st, "hits", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "misses", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "nocache", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "hits", rc_hits); rrddim_set(st, "misses", rc_misses); rrddim_set(st, "nocache", rc_nocache); rrdset_done(st); } // -------------------------------------------------------------------- if(do_fh == 2) { st = rrdset_find_bytype("nfsd", "filehandles"); if(!st) { st = rrdset_create("nfsd", "filehandles", NULL, "filehandles", NULL, "NFS Server File Handles", "handles/s", 5001, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "stale", NULL, 1, 1, RRDDIM_ABSOLUTE); rrddim_add(st, "total_lookups", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "anonymous_lookups", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "dir_not_in_dcache", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "non_dir_not_in_dcache", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "stale", fh_stale); rrddim_set(st, "total_lookups", fh_total_lookups); rrddim_set(st, "anonymous_lookups", fh_anonymous_lookups); rrddim_set(st, "dir_not_in_dcache", fh_dir_not_in_dcache); rrddim_set(st, "non_dir_not_in_dcache", fh_non_dir_not_in_dcache); rrdset_done(st); } // -------------------------------------------------------------------- if(do_io == 2) { st = rrdset_find_bytype("nfsd", "io"); if(!st) { st = rrdset_create("nfsd", "io", NULL, "io", NULL, "NFS Server I/O", "kilobytes/s", 5002, update_every, RRDSET_TYPE_AREA); rrddim_add(st, "read", NULL, 1, 1000, RRDDIM_INCREMENTAL); rrddim_add(st, "write", NULL, -1, 1000, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "read", io_read); rrddim_set(st, "write", io_write); rrdset_done(st); } // -------------------------------------------------------------------- if(do_th == 2) { st = rrdset_find_bytype("nfsd", "threads"); if(!st) { st = rrdset_create("nfsd", "threads", NULL, "threads", NULL, "NFS Server Threads", "threads", 5003, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "threads", NULL, 1, 1, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "threads", th_threads); rrdset_done(st); st = rrdset_find_bytype("nfsd", "threads_fullcnt"); if(!st) { st = rrdset_create("nfsd", "threads_fullcnt", NULL, "threads", NULL, "NFS Server Threads Full Count", "ops/s", 5004, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "full_count", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); rrddim_set(st, "full_count", th_fullcnt); rrdset_done(st); st = rrdset_find_bytype("nfsd", "threads_histogram"); if(!st) { st = rrdset_create("nfsd", "threads_histogram", NULL, "threads", NULL, "NFS Server Threads Usage Histogram", "percentage", 5005, update_every, RRDSET_TYPE_LINE); rrddim_add(st, "0%-10%", NULL, 1, 1000, RRDDIM_ABSOLUTE); rrddim_add(st, "10%-20%", NULL, 1, 1000, RRDDIM_ABSOLUTE); rrddim_add(st, "20%-30%", NULL, 1, 1000, RRDDIM_ABSOLUTE); rrddim_add(st, "30%-40%", NULL, 1, 1000, RRDDIM_ABSOLUTE); rrddim_add(st, "40%-50%", NULL, 1, 1000, RRDDIM_ABSOLUTE); rrddim_add(st, "50%-60%", NULL, 1, 1000, RRDDIM_ABSOLUTE); rrddim_add(st, "60%-70%", NULL, 1, 1000, RRDDIM_ABSOLUTE); rrddim_add(st, "70%-80%", NULL, 1, 1000, RRDDIM_ABSOLUTE); rrddim_add(st, "80%-90%", NULL, 1, 1000, RRDDIM_ABSOLUTE); rrddim_add(st, "90%-100%", NULL, 1, 1000, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "0%-10%", th_hist10); rrddim_set(st, "10%-20%", th_hist20); rrddim_set(st, "20%-30%", th_hist30); rrddim_set(st, "30%-40%", th_hist40); rrddim_set(st, "40%-50%", th_hist50); rrddim_set(st, "50%-60%", th_hist60); rrddim_set(st, "60%-70%", th_hist70); rrddim_set(st, "70%-80%", th_hist80); rrddim_set(st, "80%-90%", th_hist90); rrddim_set(st, "90%-100%", th_hist100); rrdset_done(st); } // -------------------------------------------------------------------- if(do_ra == 2) { st = rrdset_find_bytype("nfsd", "readahead"); if(!st) { st = rrdset_create("nfsd", "readahead", NULL, "readahead", NULL, "NFS Server Read Ahead Depth", "percentage", 5005, update_every, RRDSET_TYPE_STACKED); rrddim_add(st, "10%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "20%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "30%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "40%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "50%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "60%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "70%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "80%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "90%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "100%", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); rrddim_add(st, "misses", NULL, 1, 1, RRDDIM_PCENT_OVER_DIFF_TOTAL); } else rrdset_next(st); // ignore ra_size if(ra_size) {}; rrddim_set(st, "10%", ra_hist10); rrddim_set(st, "20%", ra_hist20); rrddim_set(st, "30%", ra_hist30); rrddim_set(st, "40%", ra_hist40); rrddim_set(st, "50%", ra_hist50); rrddim_set(st, "60%", ra_hist60); rrddim_set(st, "70%", ra_hist70); rrddim_set(st, "80%", ra_hist80); rrddim_set(st, "90%", ra_hist90); rrddim_set(st, "100%", ra_hist100); rrddim_set(st, "misses", ra_none); rrdset_done(st); } // -------------------------------------------------------------------- if(do_net == 2) { st = rrdset_find_bytype("nfsd", "net"); if(!st) { st = rrdset_create("nfsd", "net", NULL, "network", NULL, "NFS Server Network Statistics", "packets/s", 5007, update_every, RRDSET_TYPE_STACKED); st->isdetail = 1; rrddim_add(st, "udp", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "tcp", NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); // ignore net_count, net_tcp_connections if(net_count) {}; if(net_tcp_connections) {}; rrddim_set(st, "udp", net_udp_count); rrddim_set(st, "tcp", net_tcp_count); rrdset_done(st); } // -------------------------------------------------------------------- if(do_rpc == 2) { st = rrdset_find_bytype("nfsd", "rpc"); if(!st) { st = rrdset_create("nfsd", "rpc", NULL, "rpc", NULL, "NFS Server Remote Procedure Calls Statistics", "calls/s", 5008, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "calls", NULL, 1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "bad_format", NULL, -1, 1, RRDDIM_INCREMENTAL); rrddim_add(st, "bad_auth", NULL, -1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); // ignore rpc_bad_client if(rpc_bad_client) {}; rrddim_set(st, "calls", rpc_calls); rrddim_set(st, "bad_format", rpc_bad_format); rrddim_set(st, "bad_auth", rpc_bad_auth); rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc2 == 2) { unsigned int i; st = rrdset_find_bytype("nfsd", "proc2"); if(!st) { st = rrdset_create("nfsd", "proc2", NULL, "nfsv2rpc", NULL, "NFS v2 Server Remote Procedure Calls", "calls/s", 5009, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfsd_proc2_values[i].present ; i++) rrddim_add(st, nfsd_proc2_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); for(i = 0; nfsd_proc2_values[i].present ; i++) rrddim_set(st, nfsd_proc2_values[i].name, nfsd_proc2_values[i].value); rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc3 == 2) { unsigned int i; st = rrdset_find_bytype("nfsd", "proc3"); if(!st) { st = rrdset_create("nfsd", "proc3", NULL, "nfsv3rpc", NULL, "NFS v3 Server Remote Procedure Calls", "calls/s", 5010, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfsd_proc3_values[i].present ; i++) rrddim_add(st, nfsd_proc3_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); for(i = 0; nfsd_proc3_values[i].present ; i++) rrddim_set(st, nfsd_proc3_values[i].name, nfsd_proc3_values[i].value); rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc4 == 2) { unsigned int i; st = rrdset_find_bytype("nfsd", "proc4"); if(!st) { st = rrdset_create("nfsd", "proc4", NULL, "nfsv4rpc", NULL, "NFS v4 Server Remote Procedure Calls", "calls/s", 5011, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfsd_proc4_values[i].present ; i++) rrddim_add(st, nfsd_proc4_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); for(i = 0; nfsd_proc4_values[i].present ; i++) rrddim_set(st, nfsd_proc4_values[i].name, nfsd_proc4_values[i].value); rrdset_done(st); } // -------------------------------------------------------------------- if(do_proc4ops == 2) { unsigned int i; st = rrdset_find_bytype("nfsd", "proc4ops"); if(!st) { st = rrdset_create("nfsd", "proc4ops", NULL, "nfsv2ops", NULL, "NFS v4 Server Operations", "operations/s", 5012, update_every, RRDSET_TYPE_STACKED); for(i = 0; nfsd4_ops_values[i].present ; i++) rrddim_add(st, nfsd4_ops_values[i].name, NULL, 1, 1, RRDDIM_INCREMENTAL); } else rrdset_next(st); for(i = 0; nfsd4_ops_values[i].present ; i++) rrddim_set(st, nfsd4_ops_values[i].name, nfsd4_ops_values[i].value); rrdset_done(st); } return 0; }