void read_cgroup_plugin_configuration() { cgroup_check_for_new_every = config_get_number("plugin:cgroups", "check for new cgroups every", cgroup_check_for_new_every); cgroup_enable_cpuacct_stat = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct stat", cgroup_enable_cpuacct_stat); cgroup_enable_cpuacct_usage = config_get_boolean_ondemand("plugin:cgroups", "enable cpuacct usage", cgroup_enable_cpuacct_usage); cgroup_enable_memory = config_get_boolean_ondemand("plugin:cgroups", "enable memory", cgroup_enable_memory); cgroup_enable_blkio = config_get_boolean_ondemand("plugin:cgroups", "enable blkio", cgroup_enable_blkio); char filename[FILENAME_MAX + 1], *s; struct mountinfo *mi, *root = mountinfo_read(); mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "cpuacct"); if(!mi) mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "cpuacct"); if(!mi) { error("Cannot find cgroup cpuacct mountinfo. Assuming default: /sys/fs/cgroup/cpuacct"); s = "/sys/fs/cgroup/cpuacct"; } else s = mi->mount_point; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s); cgroup_cpuacct_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/cpuacct", filename); mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "blkio"); if(!mi) mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "blkio"); if(!mi) { error("Cannot find cgroup blkio mountinfo. Assuming default: /sys/fs/cgroup/blkio"); s = "/sys/fs/cgroup/blkio"; } else s = mi->mount_point; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s); cgroup_blkio_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/blkio", filename); mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "memory"); if(!mi) mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "memory"); if(!mi) { error("Cannot find cgroup memory mountinfo. Assuming default: /sys/fs/cgroup/memory"); s = "/sys/fs/cgroup/memory"; } else s = mi->mount_point; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s); cgroup_memory_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/memory", filename); mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "devices"); if(!mi) mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "devices"); if(!mi) { error("Cannot find cgroup devices mountinfo. Assuming default: /sys/fs/cgroup/devices"); s = "/sys/fs/cgroup/devices"; } else s = mi->mount_point; snprintfz(filename, FILENAME_MAX, "%s%s", global_host_prefix, s); cgroup_devices_base = config_get("plugin:cgroups", "path to /sys/fs/cgroup/devices", filename); cgroup_root_max = config_get_number("plugin:cgroups", "max cgroups to allow", cgroup_root_max); cgroup_max_depth = config_get_number("plugin:cgroups", "max cgroups depth to monitor", cgroup_max_depth); cgroup_enable_new_cgroups_detected_at_runtime = config_get_boolean("plugin:cgroups", "enable new cgroups detected at run time", cgroup_enable_new_cgroups_detected_at_runtime); mountinfo_free(root); }
static inline void do_disk_space_stats(struct mountinfo *mi, int update_every) { const char *family = mi->mount_point; const char *disk = mi->persistent_id; static SIMPLE_PATTERN *excluded_mountpoints = NULL; static SIMPLE_PATTERN *excluded_filesystems = NULL; int do_space, do_inodes; if(unlikely(!dict_mountpoints)) { SIMPLE_PREFIX_MODE mode = SIMPLE_PATTERN_EXACT; if(config_move("plugin:proc:/proc/diskstats", "exclude space metrics on paths", CONFIG_SECTION_DISKSPACE, "exclude space metrics on paths") != -1) { // old configuration, enable backwards compatibility mode = SIMPLE_PATTERN_PREFIX; } excluded_mountpoints = simple_pattern_create( config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on paths", DELAULT_EXLUDED_PATHS), mode ); excluded_filesystems = simple_pattern_create( config_get(CONFIG_SECTION_DISKSPACE, "exclude space metrics on filesystems", DEFAULT_EXCLUDED_FILESYSTEMS), SIMPLE_PATTERN_EXACT ); dict_mountpoints = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); } struct mount_point_metadata *m = dictionary_get(dict_mountpoints, mi->mount_point); if(unlikely(!m)) { char var_name[4096 + 1]; snprintfz(var_name, 4096, "plugin:proc:diskspace:%s", mi->mount_point); int def_space = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "space usage for all disks", CONFIG_BOOLEAN_AUTO); int def_inodes = config_get_boolean_ondemand(CONFIG_SECTION_DISKSPACE, "inodes usage for all disks", CONFIG_BOOLEAN_AUTO); if(unlikely(simple_pattern_matches(excluded_mountpoints, mi->mount_point))) { def_space = CONFIG_BOOLEAN_NO; def_inodes = CONFIG_BOOLEAN_NO; } if(unlikely(simple_pattern_matches(excluded_filesystems, mi->filesystem))) { def_space = CONFIG_BOOLEAN_NO; def_inodes = CONFIG_BOOLEAN_NO; } // check if the mount point is a directory #2407 { struct stat bs; if(stat(mi->mount_point, &bs) == -1) { error("DISKSPACE: Cannot stat() mount point '%s' (disk '%s', filesystem '%s', root '%s')." , mi->mount_point , disk , mi->filesystem?mi->filesystem:"" , mi->root?mi->root:"" ); def_space = CONFIG_BOOLEAN_NO; def_inodes = CONFIG_BOOLEAN_NO; } else { if((bs.st_mode & S_IFMT) != S_IFDIR) { error("DISKSPACE: Mount point '%s' (disk '%s', filesystem '%s', root '%s') is not a directory." , mi->mount_point , disk , mi->filesystem?mi->filesystem:"" , mi->root?mi->root:"" ); def_space = CONFIG_BOOLEAN_NO; def_inodes = CONFIG_BOOLEAN_NO; } } } do_space = config_get_boolean_ondemand(var_name, "space usage", def_space); do_inodes = config_get_boolean_ondemand(var_name, "inodes usage", def_inodes); struct mount_point_metadata mp = { .do_space = do_space, .do_inodes = do_inodes, .shown_error = 0, .updated = 0, .collected = 0, .st_space = NULL, .rd_space_avail = NULL, .rd_space_used = NULL, .rd_space_reserved = NULL, .st_inodes = NULL, .rd_inodes_avail = NULL, .rd_inodes_used = NULL, .rd_inodes_reserved = NULL }; m = dictionary_set(dict_mountpoints, mi->mount_point, &mp, sizeof(struct mount_point_metadata)); } m->updated = 1; if(unlikely(m->do_space == CONFIG_BOOLEAN_NO && m->do_inodes == CONFIG_BOOLEAN_NO)) return; if(unlikely(mi->flags & MOUNTINFO_READONLY && !m->collected)) return; struct statvfs buff_statvfs; if (statvfs(mi->mount_point, &buff_statvfs) < 0) { if(!m->shown_error) { error("DISKSPACE: failed to statvfs() mount point '%s' (disk '%s', filesystem '%s', root '%s')" , mi->mount_point , disk , mi->filesystem?mi->filesystem:"" , mi->root?mi->root:"" ); m->shown_error = 1; } return; } m->shown_error = 0; // logic found at get_fs_usage() in coreutils unsigned long bsize = (buff_statvfs.f_frsize) ? buff_statvfs.f_frsize : buff_statvfs.f_bsize; fsblkcnt_t bavail = buff_statvfs.f_bavail; fsblkcnt_t btotal = buff_statvfs.f_blocks; fsblkcnt_t bavail_root = buff_statvfs.f_bfree; fsblkcnt_t breserved_root = bavail_root - bavail; fsblkcnt_t bused; if(likely(btotal >= bavail_root)) bused = btotal - bavail_root; else bused = bavail_root - btotal; #ifdef NETDATA_INTERNAL_CHECKS if(unlikely(btotal != bavail + breserved_root + bused)) error("DISKSPACE: disk block statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mi->mount_point, disk, (unsigned long long)btotal, (unsigned long long)bavail, (unsigned long long)breserved_root, (unsigned long long)bused); #endif // -------------------------------------------------------------------------- fsfilcnt_t favail = buff_statvfs.f_favail; fsfilcnt_t ftotal = buff_statvfs.f_files; fsfilcnt_t favail_root = buff_statvfs.f_ffree; fsfilcnt_t freserved_root = favail_root - favail; fsfilcnt_t fused = ftotal - favail_root; #ifdef NETDATA_INTERNAL_CHECKS if(unlikely(btotal != bavail + breserved_root + bused)) error("DISKSPACE: disk inode statistics for '%s' (disk '%s') do not sum up: total = %llu, available = %llu, reserved = %llu, used = %llu", mi->mount_point, disk, (unsigned long long)ftotal, (unsigned long long)favail, (unsigned long long)freserved_root, (unsigned long long)fused); #endif // -------------------------------------------------------------------------- int rendered = 0; if(m->do_space == CONFIG_BOOLEAN_YES || (m->do_space == CONFIG_BOOLEAN_AUTO && (bavail || breserved_root || bused))) { if(unlikely(!m->st_space)) { m->do_space = CONFIG_BOOLEAN_YES; m->st_space = rrdset_find_bytype_localhost("disk_space", disk); if(unlikely(!m->st_space)) { char title[4096 + 1]; snprintfz(title, 4096, "Disk Space Usage for %s [%s]", family, mi->mount_source); m->st_space = rrdset_create_localhost( "disk_space" , disk , NULL , family , "disk.space" , title , "GB" , 2023 , update_every , RRDSET_TYPE_STACKED ); } m->rd_space_avail = rrddim_add(m->st_space, "avail", NULL, (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); m->rd_space_used = rrddim_add(m->st_space, "used", NULL, (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); m->rd_space_reserved = rrddim_add(m->st_space, "reserved_for_root", "reserved for root", (collected_number)bsize, 1024 * 1024 * 1024, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(m->st_space); rrddim_set_by_pointer(m->st_space, m->rd_space_avail, (collected_number)bavail); rrddim_set_by_pointer(m->st_space, m->rd_space_used, (collected_number)bused); rrddim_set_by_pointer(m->st_space, m->rd_space_reserved, (collected_number)breserved_root); rrdset_done(m->st_space); rendered++; } // -------------------------------------------------------------------------- if(m->do_inodes == CONFIG_BOOLEAN_YES || (m->do_inodes == CONFIG_BOOLEAN_AUTO && (favail || freserved_root || fused))) { if(unlikely(!m->st_inodes)) { m->do_inodes = CONFIG_BOOLEAN_YES; m->st_inodes = rrdset_find_bytype_localhost("disk_inodes", disk); if(unlikely(!m->st_inodes)) { char title[4096 + 1]; snprintfz(title, 4096, "Disk Files (inodes) Usage for %s [%s]", family, mi->mount_source); m->st_inodes = rrdset_create_localhost( "disk_inodes" , disk , NULL , family , "disk.inodes" , title , "Inodes" , 2024 , update_every , RRDSET_TYPE_STACKED ); } m->rd_inodes_avail = rrddim_add(m->st_inodes, "avail", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); m->rd_inodes_used = rrddim_add(m->st_inodes, "used", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); m->rd_inodes_reserved = rrddim_add(m->st_inodes, "reserved_for_root", "reserved for root", 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(m->st_inodes); rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_avail, (collected_number)favail); rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_used, (collected_number)fused); rrddim_set_by_pointer(m->st_inodes, m->rd_inodes_reserved, (collected_number)freserved_root); rrdset_done(m->st_inodes); rendered++; } // -------------------------------------------------------------------------- if(likely(rendered)) m->collected++; }
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; }
int do_proc_vmstat(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; static int do_swapio = -1, do_io = -1, do_pgfaults = -1, do_numa = -1; static int has_numa = -1; static ARL_BASE *arl_base = NULL; static unsigned long long numa_foreign = 0ULL; static unsigned long long numa_hint_faults = 0ULL; static unsigned long long numa_hint_faults_local = 0ULL; static unsigned long long numa_huge_pte_updates = 0ULL; static unsigned long long numa_interleave = 0ULL; static unsigned long long numa_local = 0ULL; static unsigned long long numa_other = 0ULL; static unsigned long long numa_pages_migrated = 0ULL; static unsigned long long numa_pte_updates = 0ULL; static unsigned long long pgfault = 0ULL; static unsigned long long pgmajfault = 0ULL; static unsigned long long pgpgin = 0ULL; static unsigned long long pgpgout = 0ULL; static unsigned long long pswpin = 0ULL; static unsigned long long pswpout = 0ULL; if(unlikely(!arl_base)) { do_swapio = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "swap i/o", CONFIG_BOOLEAN_AUTO); do_io = config_get_boolean("plugin:proc:/proc/vmstat", "disk i/o", 1); do_pgfaults = config_get_boolean("plugin:proc:/proc/vmstat", "memory page faults", 1); do_numa = config_get_boolean_ondemand("plugin:proc:/proc/vmstat", "system-wide numa metric summary", CONFIG_BOOLEAN_AUTO); arl_base = arl_create("vmstat", NULL, 60); arl_expect(arl_base, "pgfault", &pgfault); arl_expect(arl_base, "pgmajfault", &pgmajfault); arl_expect(arl_base, "pgpgin", &pgpgin); arl_expect(arl_base, "pgpgout", &pgpgout); arl_expect(arl_base, "pswpin", &pswpin); arl_expect(arl_base, "pswpout", &pswpout); if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && get_numa_node_count() >= 2)) { arl_expect(arl_base, "numa_foreign", &numa_foreign); arl_expect(arl_base, "numa_hint_faults_local", &numa_hint_faults_local); arl_expect(arl_base, "numa_hint_faults", &numa_hint_faults); arl_expect(arl_base, "numa_huge_pte_updates", &numa_huge_pte_updates); arl_expect(arl_base, "numa_interleave", &numa_interleave); arl_expect(arl_base, "numa_local", &numa_local); arl_expect(arl_base, "numa_other", &numa_other); arl_expect(arl_base, "numa_pages_migrated", &numa_pages_migrated); arl_expect(arl_base, "numa_pte_updates", &numa_pte_updates); } else { // Do not expect numa metrics when they are not needed. // By not adding them, the ARL will stop processing the file // when all the expected metrics are collected. // Also ARL will not parse their values. has_numa = 0; do_numa = CONFIG_BOOLEAN_NO; } } if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/vmstat"); ff = procfile_open(config_get("plugin:proc:/proc/vmstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) return 1; } ff = procfile_readall(ff); if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time size_t lines = procfile_lines(ff), l; arl_begin(arl_base); for(l = 0; l < lines ;l++) { size_t words = procfile_linewords(ff, l); if(unlikely(words < 2)) { if(unlikely(words)) error("Cannot read /proc/vmstat line %zu. Expected 2 params, read %zu.", l, words); continue; } if(unlikely(arl_check(arl_base, procfile_lineword(ff, l, 0), procfile_lineword(ff, l, 1)))) break; } // -------------------------------------------------------------------- if(pswpin || pswpout || do_swapio == CONFIG_BOOLEAN_YES) { do_swapio = CONFIG_BOOLEAN_YES; static RRDSET *st_swapio = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; if(unlikely(!st_swapio)) { st_swapio = rrdset_create_localhost( "system" , "swapio" , NULL , "swap" , NULL , "Swap I/O" , "kilobytes/s" , 250 , update_every , RRDSET_TYPE_AREA ); rd_in = rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_swapio); rrddim_set_by_pointer(st_swapio, rd_in, pswpin); rrddim_set_by_pointer(st_swapio, rd_out, pswpout); rrdset_done(st_swapio); } // -------------------------------------------------------------------- if(do_io) { static RRDSET *st_io = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; if(unlikely(!st_io)) { st_io = rrdset_create_localhost( "system" , "io" , NULL , "disk" , NULL , "Disk I/O" , "kilobytes/s" , 150 , update_every , RRDSET_TYPE_AREA ); rd_in = rrddim_add(st_io, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st_io, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_io); rrddim_set_by_pointer(st_io, rd_in, pgpgin); rrddim_set_by_pointer(st_io, rd_out, pgpgout); rrdset_done(st_io); } // -------------------------------------------------------------------- if(do_pgfaults) { static RRDSET *st_pgfaults = NULL; static RRDDIM *rd_minor = NULL, *rd_major = NULL; if(unlikely(!st_pgfaults)) { st_pgfaults = rrdset_create_localhost( "mem" , "pgfaults" , NULL , "system" , NULL , "Memory Page Faults" , "page faults/s" , 500 , update_every , RRDSET_TYPE_LINE ); rrdset_flag_set(st_pgfaults, RRDSET_FLAG_DETAIL); rd_minor = rrddim_add(st_pgfaults, "minor", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_major = rrddim_add(st_pgfaults, "major", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_pgfaults); rrddim_set_by_pointer(st_pgfaults, rd_minor, pgfault); rrddim_set_by_pointer(st_pgfaults, rd_major, pgmajfault); rrdset_done(st_pgfaults); } // -------------------------------------------------------------------- // Ondemand criteria for NUMA. Since this won't change at run time, we // check it only once. We check whether the node count is >= 2 because // single-node systems have uninteresting statistics (since all accesses // are local). if(unlikely(has_numa == -1)) has_numa = (numa_local || numa_foreign || numa_interleave || numa_other || numa_pte_updates || numa_huge_pte_updates || numa_hint_faults || numa_hint_faults_local || numa_pages_migrated) ? 1 : 0; if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && has_numa)) { do_numa = CONFIG_BOOLEAN_YES; static RRDSET *st_numa = NULL; static RRDDIM *rd_local = NULL, *rd_foreign = NULL, *rd_interleave = NULL, *rd_other = NULL, *rd_pte_updates = NULL, *rd_huge_pte_updates = NULL, *rd_hint_faults = NULL, *rd_hint_faults_local = NULL, *rd_pages_migrated = NULL; if(unlikely(!st_numa)) { st_numa = rrdset_create_localhost( "mem" , "numa" , NULL , "numa" , NULL , "NUMA events" , "events/s" , 800 , update_every , RRDSET_TYPE_LINE ); rrdset_flag_set(st_numa, RRDSET_FLAG_DETAIL); // These depend on CONFIG_NUMA in the kernel. rd_local = rrddim_add(st_numa, "local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_foreign = rrddim_add(st_numa, "foreign", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_interleave = rrddim_add(st_numa, "interleave", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_other = rrddim_add(st_numa, "other", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); // The following stats depend on CONFIG_NUMA_BALANCING in the // kernel. rd_pte_updates = rrddim_add(st_numa, "pte_updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_huge_pte_updates = rrddim_add(st_numa, "huge_pte_updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_hint_faults = rrddim_add(st_numa, "hint_faults", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_hint_faults_local = rrddim_add(st_numa, "hint_faults_local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); rd_pages_migrated = rrddim_add(st_numa, "pages_migrated", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st_numa); rrddim_set_by_pointer(st_numa, rd_local, numa_local); rrddim_set_by_pointer(st_numa, rd_foreign, numa_foreign); rrddim_set_by_pointer(st_numa, rd_interleave, numa_interleave); rrddim_set_by_pointer(st_numa, rd_other, numa_other); rrddim_set_by_pointer(st_numa, rd_pte_updates, numa_pte_updates); rrddim_set_by_pointer(st_numa, rd_huge_pte_updates, numa_huge_pte_updates); rrddim_set_by_pointer(st_numa, rd_hint_faults, numa_hint_faults); rrddim_set_by_pointer(st_numa, rd_hint_faults_local, numa_hint_faults_local); rrddim_set_by_pointer(st_numa, rd_pages_migrated, numa_pages_migrated); rrdset_done(st_numa); } return 0; }
int 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_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; }
int do_proc_net_sockstat6(int update_every, usec_t dt) { (void)dt; static procfile *ff = NULL; static uint32_t hash_raw = 0, hash_frag = 0, hash_tcp = 0, hash_udp = 0, hash_udplite = 0; static ARL_BASE *arl_tcp = NULL; static ARL_BASE *arl_udp = NULL; static ARL_BASE *arl_udplite = NULL; static ARL_BASE *arl_raw = NULL; static ARL_BASE *arl_frag = NULL; static int do_tcp_sockets = -1, do_udp_sockets = -1, do_udplite_sockets = -1, do_raw_sockets = -1, do_frag_sockets = -1; static char *keys[6] = { NULL }; static uint32_t hashes[6] = { 0 }; static ARL_BASE *bases[6] = { NULL }; if(unlikely(!arl_tcp)) { do_tcp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 TCP sockets", CONFIG_BOOLEAN_AUTO); do_udp_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDP sockets", CONFIG_BOOLEAN_AUTO); do_udplite_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 UDPLITE sockets", CONFIG_BOOLEAN_AUTO); do_raw_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 RAW sockets", CONFIG_BOOLEAN_AUTO); do_frag_sockets = config_get_boolean_ondemand("plugin:proc:/proc/net/sockstat6", "ipv6 FRAG sockets", CONFIG_BOOLEAN_AUTO); arl_tcp = arl_create("sockstat6/TCP6", arl_callback_str2kernel_uint_t, 60); arl_expect(arl_tcp, "inuse", &sockstat6_root.tcp6_inuse); arl_udp = arl_create("sockstat6/UDP6", arl_callback_str2kernel_uint_t, 60); arl_expect(arl_udp, "inuse", &sockstat6_root.udp6_inuse); arl_udplite = arl_create("sockstat6/UDPLITE6", arl_callback_str2kernel_uint_t, 60); arl_expect(arl_udplite, "inuse", &sockstat6_root.udplite6_inuse); arl_raw = arl_create("sockstat6/RAW6", arl_callback_str2kernel_uint_t, 60); arl_expect(arl_raw, "inuse", &sockstat6_root.raw6_inuse); arl_frag = arl_create("sockstat6/FRAG6", arl_callback_str2kernel_uint_t, 60); arl_expect(arl_frag, "inuse", &sockstat6_root.frag6_inuse); hash_tcp = simple_hash("TCP6"); hash_udp = simple_hash("UDP6"); hash_udplite = simple_hash("UDPLITE6"); hash_raw = simple_hash("RAW6"); hash_frag = simple_hash("FRAG6"); keys[0] = "TCP6"; hashes[0] = hash_tcp; bases[0] = arl_tcp; keys[1] = "UDP6"; hashes[1] = hash_udp; bases[1] = arl_udp; keys[2] = "UDPLITE6"; hashes[2] = hash_udplite; bases[2] = arl_udplite; keys[3] = "RAW6"; hashes[3] = hash_raw; bases[3] = arl_raw; keys[4] = "FRAG6"; hashes[4] = hash_frag; bases[4] = arl_frag; keys[5] = NULL; // terminator } if(unlikely(!ff)) { char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/net/sockstat6"); ff = procfile_open(config_get("plugin:proc:/proc/net/sockstat6", "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; for(l = 0; l < lines ;l++) { size_t words = procfile_linewords(ff, l); char *key = procfile_lineword(ff, l, 0); uint32_t hash = simple_hash(key); int k; for(k = 0; keys[k] ; k++) { if(unlikely(hash == hashes[k] && strcmp(key, keys[k]) == 0)) { // fprintf(stderr, "KEY: '%s', l=%zu, w=1, words=%zu\n", key, l, words); ARL_BASE *arl = bases[k]; arl_begin(arl); size_t w = 1; while(w + 1 < words) { char *name = procfile_lineword(ff, l, w); w++; char *value = procfile_lineword(ff, l, w); w++; // fprintf(stderr, " > NAME '%s', VALUE '%s', l=%zu, w=%zu, words=%zu\n", name, value, l, w, words); if(unlikely(arl_check(arl, name, value) != 0)) break; } break; } } } // ------------------------------------------------------------------------ if(do_tcp_sockets == CONFIG_BOOLEAN_YES || (do_tcp_sockets == CONFIG_BOOLEAN_AUTO && (sockstat6_root.tcp6_inuse))) { do_tcp_sockets = CONFIG_BOOLEAN_YES; static RRDSET *st = NULL; static RRDDIM *rd_inuse = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "ipv6" , "sockstat6_tcp_sockets" , NULL , "tcp6" , NULL , "IPv6 TCP Sockets" , "sockets" , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME , NETDATA_CHART_PRIO_IPV6_TCP , update_every , RRDSET_TYPE_LINE ); rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.tcp6_inuse); rrdset_done(st); } // ------------------------------------------------------------------------ if(do_udp_sockets == CONFIG_BOOLEAN_YES || (do_udp_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.udp6_inuse)) { do_udp_sockets = CONFIG_BOOLEAN_YES; static RRDSET *st = NULL; static RRDDIM *rd_inuse = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "ipv6" , "sockstat6_udp_sockets" , NULL , "udp6" , NULL , "IPv6 UDP Sockets" , "sockets" , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME , NETDATA_CHART_PRIO_IPV6_UDP , update_every , RRDSET_TYPE_LINE ); rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.udp6_inuse); rrdset_done(st); } // ------------------------------------------------------------------------ if(do_udplite_sockets == CONFIG_BOOLEAN_YES || (do_udplite_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.udplite6_inuse)) { do_udplite_sockets = CONFIG_BOOLEAN_YES; static RRDSET *st = NULL; static RRDDIM *rd_inuse = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "ipv6" , "sockstat6_udplite_sockets" , NULL , "udplite6" , NULL , "IPv6 UDPLITE Sockets" , "sockets" , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME , NETDATA_CHART_PRIO_IPV6_UDPLITE , update_every , RRDSET_TYPE_LINE ); rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.udplite6_inuse); rrdset_done(st); } // ------------------------------------------------------------------------ if(do_raw_sockets == CONFIG_BOOLEAN_YES || (do_raw_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.raw6_inuse)) { do_raw_sockets = CONFIG_BOOLEAN_YES; static RRDSET *st = NULL; static RRDDIM *rd_inuse = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "ipv6" , "sockstat6_raw_sockets" , NULL , "raw6" , NULL , "IPv6 RAW Sockets" , "sockets" , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME , NETDATA_CHART_PRIO_IPV6_RAW , update_every , RRDSET_TYPE_LINE ); rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.raw6_inuse); rrdset_done(st); } // ------------------------------------------------------------------------ if(do_frag_sockets == CONFIG_BOOLEAN_YES || (do_frag_sockets == CONFIG_BOOLEAN_AUTO && sockstat6_root.frag6_inuse)) { do_frag_sockets = CONFIG_BOOLEAN_YES; static RRDSET *st = NULL; static RRDDIM *rd_inuse = NULL; if(unlikely(!st)) { st = rrdset_create_localhost( "ipv6" , "sockstat6_frag_sockets" , NULL , "fragments6" , NULL , "IPv6 FRAG Sockets" , "fragments" , PLUGIN_PROC_NAME , PLUGIN_PROC_MODULE_NET_SOCKSTAT6_NAME , NETDATA_CHART_PRIO_IPV6_FRAGMENTS , update_every , RRDSET_TYPE_LINE ); rd_inuse = rrddim_add(st, "inuse", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else rrdset_next(st); rrddim_set_by_pointer(st, rd_inuse, (collected_number)sockstat6_root.frag6_inuse); rrdset_done(st); } return 0; }
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; }
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_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; }
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; }
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; }
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 inline void tc_device_commit(struct tc_device *d) { static int enable_new_interfaces = -1, enable_bytes = -1, enable_packets = -1, enable_dropped = -1, enable_tokens = -1, enable_ctokens = -1, enabled_all_classes_qdiscs = -1; if(unlikely(enable_new_interfaces == -1)) { enable_new_interfaces = config_get_boolean_ondemand("plugin:tc", "enable new interfaces detected at runtime", CONFIG_BOOLEAN_YES); enable_bytes = config_get_boolean_ondemand("plugin:tc", "enable traffic charts for all interfaces", CONFIG_BOOLEAN_AUTO); enable_packets = config_get_boolean_ondemand("plugin:tc", "enable packets charts for all interfaces", CONFIG_BOOLEAN_AUTO); enable_dropped = config_get_boolean_ondemand("plugin:tc", "enable dropped charts for all interfaces", CONFIG_BOOLEAN_AUTO); enable_tokens = config_get_boolean_ondemand("plugin:tc", "enable tokens charts for all interfaces", CONFIG_BOOLEAN_NO); enable_ctokens = config_get_boolean_ondemand("plugin:tc", "enable ctokens charts for all interfaces", CONFIG_BOOLEAN_NO); enabled_all_classes_qdiscs = config_get_boolean_ondemand("plugin:tc", "enable show all classes and qdiscs for all interfaces", CONFIG_BOOLEAN_NO); } if(unlikely(d->enabled == (char)-1)) { char var_name[CONFIG_MAX_NAME + 1]; snprintfz(var_name, CONFIG_MAX_NAME, "qos for %s", d->id); d->enabled = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_new_interfaces); snprintfz(var_name, CONFIG_MAX_NAME, "traffic chart for %s", d->id); d->enabled_bytes = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_bytes); snprintfz(var_name, CONFIG_MAX_NAME, "packets chart for %s", d->id); d->enabled_packets = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_packets); snprintfz(var_name, CONFIG_MAX_NAME, "dropped packets chart for %s", d->id); d->enabled_dropped = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_dropped); snprintfz(var_name, CONFIG_MAX_NAME, "tokens chart for %s", d->id); d->enabled_tokens = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_tokens); snprintfz(var_name, CONFIG_MAX_NAME, "ctokens chart for %s", d->id); d->enabled_ctokens = (char)config_get_boolean_ondemand("plugin:tc", var_name, enable_ctokens); snprintfz(var_name, CONFIG_MAX_NAME, "show all classes for %s", d->id); d->enabled_all_classes_qdiscs = (char)config_get_boolean_ondemand("plugin:tc", var_name, enabled_all_classes_qdiscs); } // we only need to add leaf classes struct tc_class *c, *x /*, *root = NULL */; unsigned long long bytes_sum = 0, packets_sum = 0, dropped_sum = 0, tokens_sum = 0, ctokens_sum = 0; int active_nodes = 0, updated_classes = 0, updated_qdiscs = 0; // prepare all classes // we set reasonable defaults for the rest of the code below for(c = d->classes ; c ; c = c->next) { c->render = 0; // do not render this class c->isleaf = 1; // this is a leaf class c->hasparent = 0; // without a parent if(unlikely(!c->updated)) c->unupdated++; // increase its unupdated counter else { c->unupdated = 0; // reset its unupdated counter // count how many of each kind if(c->isqdisc) updated_qdiscs++; else updated_classes++; } } if(unlikely(!d->enabled || (!updated_classes && !updated_qdiscs))) { debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. It is not enabled/updated.", d->name?d->name:d->id); tc_device_classes_cleanup(d); return; } if(unlikely(updated_classes && updated_qdiscs)) { error("TC: device '%s' has active both classes (%d) and qdiscs (%d). Will render only qdiscs.", d->id, updated_classes, updated_qdiscs); // set all classes to !updated for(c = d->classes ; c ; c = c->next) if(unlikely(!c->isqdisc && c->updated)) c->updated = 0; updated_classes = 0; } // mark the classes as leafs and parents // // TC is hierarchical: // - classes can have other classes in them // - the same is true for qdiscs (i.e. qdiscs have classes, that have other qdiscs) // // we need to present a chart with leaf nodes only, so that the sum // of all dimensions of the chart, will be the total utilization // of the interface. // // here we try to find the ones we need to report // by default all nodes are marked with: isleaf = 1 (see above) // // so, here we remove the isleaf flag from nodes in the middle // and we add the hasparent flag to leaf nodes we found their parent if(likely(!d->enabled_all_classes_qdiscs)) { for(c = d->classes; c; c = c->next) { if(unlikely(!c->updated)) continue; //debug(D_TC_LOOP, "TC: In device '%s', %s '%s' has leafid: '%s' and parentid '%s'.", // d->id, // c->isqdisc?"qdisc":"class", // c->id, // c->leafid?c->leafid:"NULL", // c->parentid?c->parentid:"NULL"); // find if c is leaf or not for(x = d->classes; x; x = x->next) { if(unlikely(!x->updated || c == x || !x->parentid)) continue; // classes have both parentid and leafid // qdiscs have only parentid // the following works for both (it is an OR) if((c->hash == x->parent_hash && strcmp(c->id, x->parentid) == 0) || (c->leafid && c->leaf_hash == x->parent_hash && strcmp(c->leafid, x->parentid) == 0)) { // debug(D_TC_LOOP, "TC: In device '%s', %s '%s' (leafid: '%s') has as leaf %s '%s' (parentid: '%s').", d->name?d->name:d->id, c->isqdisc?"qdisc":"class", c->name?c->name:c->id, c->leafid?c->leafid:c->id, x->isqdisc?"qdisc":"class", x->name?x->name:x->id, x->parentid?x->parentid:x->id); c->isleaf = 0; x->hasparent = 1; } } } } for(c = d->classes ; c ; c = c->next) { if(unlikely(!c->updated)) continue; // debug(D_TC_LOOP, "TC: device '%s', %s '%s' isleaf=%d, hasparent=%d", d->id, (c->isqdisc)?"qdisc":"class", c->id, c->isleaf, c->hasparent); if(unlikely((c->isleaf && c->hasparent) || d->enabled_all_classes_qdiscs)) { c->render = 1; active_nodes++; bytes_sum += c->bytes; packets_sum += c->packets; dropped_sum += c->dropped; tokens_sum += c->tokens; ctokens_sum += c->ctokens; } //if(unlikely(!c->hasparent)) { // if(root) error("TC: multiple root class/qdisc for device '%s' (old: '%s', new: '%s')", d->id, root->id, c->id); // root = c; // debug(D_TC_LOOP, "TC: found root class/qdisc '%s'", root->id); //} } #ifdef NETDATA_INTERNAL_CHECKS // dump all the list to see what we know if(unlikely(debug_flags & D_TC_LOOP)) { for(c = d->classes ; c ; c = c->next) { if(c->render) debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, OK", d->name, c->id); else debug(D_TC_LOOP, "TC: final nodes dump for '%s': class %s, IGNORE (updated: %d, isleaf: %d, hasparent: %d, parent: %s)", d->name?d->name:d->id, c->id, c->updated, c->isleaf, c->hasparent, c->parentid?c->parentid:"(unset)"); } } #endif if(unlikely(!active_nodes)) { debug(D_TC_LOOP, "TC: Ignoring TC device '%s'. No useful classes/qdiscs.", d->name?d->name:d->id); tc_device_classes_cleanup(d); return; } debug(D_TC_LOOP, "TC: evaluating TC device '%s'. enabled = %d/%d (bytes: %d/%d, packets: %d/%d, dropped: %d/%d, tokens: %d/%d, ctokens: %d/%d, all_classes_qdiscs: %d/%d), classes: (bytes = %llu, packets = %llu, dropped = %llu, tokens = %llu, ctokens = %llu).", d->name?d->name:d->id, d->enabled, enable_new_interfaces, d->enabled_bytes, enable_bytes, d->enabled_packets, enable_packets, d->enabled_dropped, enable_dropped, d->enabled_tokens, enable_tokens, d->enabled_ctokens, enable_ctokens, d->enabled_all_classes_qdiscs, enabled_all_classes_qdiscs, bytes_sum, packets_sum, dropped_sum, tokens_sum, ctokens_sum ); // -------------------------------------------------------------------- // bytes if(d->enabled_bytes == CONFIG_BOOLEAN_YES || (d->enabled_bytes == CONFIG_BOOLEAN_AUTO && bytes_sum)) { d->enabled_bytes = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_bytes)) d->st_bytes = rrdset_create_localhost( RRD_TYPE_TC , d->id , d->name ? d->name : d->id , d->family ? d->family : d->id , RRD_TYPE_TC ".qos" , "Class Usage" , "kilobits/s" , PLUGIN_TC_NAME , NULL , NETDATA_CHART_PRIO_TC_QOS , localhost->rrd_update_every , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED ); else { rrdset_next(d->st_bytes); if(unlikely(d->name_updated)) rrdset_set_name(d->st_bytes, d->name); // TODO // update the family } for(c = d->classes ; c ; c = c->next) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_bytes)) c->rd_bytes = rrddim_add(d->st_bytes, c->id, c->name?c->name:c->id, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) rrddim_set_name(d->st_bytes, c->rd_bytes, c->name); rrddim_set_by_pointer(d->st_bytes, c->rd_bytes, c->bytes); } rrdset_done(d->st_bytes); } // -------------------------------------------------------------------- // packets if(d->enabled_packets == CONFIG_BOOLEAN_YES || (d->enabled_packets == CONFIG_BOOLEAN_AUTO && packets_sum)) { d->enabled_packets = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_packets)) { char id[RRD_ID_LENGTH_MAX + 1]; char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(id, RRD_ID_LENGTH_MAX, "%s_packets", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id); d->st_packets = rrdset_create_localhost( RRD_TYPE_TC , id , name , d->family ? d->family : d->id , RRD_TYPE_TC ".qos_packets" , "Class Packets" , "packets/s" , PLUGIN_TC_NAME , NULL , NETDATA_CHART_PRIO_TC_QOS_PACKETS , localhost->rrd_update_every , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED ); } else { rrdset_next(d->st_packets); if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(name, RRD_ID_LENGTH_MAX, "%s_packets", d->name?d->name:d->id); rrdset_set_name(d->st_packets, name); } // TODO // update the family } for(c = d->classes ; c ; c = c->next) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_packets)) c->rd_packets = rrddim_add(d->st_packets, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) rrddim_set_name(d->st_packets, c->rd_packets, c->name); rrddim_set_by_pointer(d->st_packets, c->rd_packets, c->packets); } rrdset_done(d->st_packets); } // -------------------------------------------------------------------- // dropped if(d->enabled_dropped == CONFIG_BOOLEAN_YES || (d->enabled_dropped == CONFIG_BOOLEAN_AUTO && dropped_sum)) { d->enabled_dropped = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_dropped)) { char id[RRD_ID_LENGTH_MAX + 1]; char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(id, RRD_ID_LENGTH_MAX, "%s_dropped", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id); d->st_dropped = rrdset_create_localhost( RRD_TYPE_TC , id , name , d->family ? d->family : d->id , RRD_TYPE_TC ".qos_dropped" , "Class Dropped Packets" , "packets/s" , PLUGIN_TC_NAME , NULL , NETDATA_CHART_PRIO_TC_QOS_DROPPED , localhost->rrd_update_every , d->enabled_all_classes_qdiscs ? RRDSET_TYPE_LINE : RRDSET_TYPE_STACKED ); } else { rrdset_next(d->st_dropped); if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(name, RRD_ID_LENGTH_MAX, "%s_dropped", d->name?d->name:d->id); rrdset_set_name(d->st_dropped, name); } // TODO // update the family } for(c = d->classes ; c ; c = c->next) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_dropped)) c->rd_dropped = rrddim_add(d->st_dropped, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_INCREMENTAL); else if(unlikely(c->name_updated)) rrddim_set_name(d->st_dropped, c->rd_dropped, c->name); rrddim_set_by_pointer(d->st_dropped, c->rd_dropped, c->dropped); } rrdset_done(d->st_dropped); } // -------------------------------------------------------------------- // tokens if(d->enabled_tokens == CONFIG_BOOLEAN_YES || (d->enabled_tokens == CONFIG_BOOLEAN_AUTO && tokens_sum)) { d->enabled_tokens = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_tokens)) { char id[RRD_ID_LENGTH_MAX + 1]; char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(id, RRD_ID_LENGTH_MAX, "%s_tokens", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", d->name?d->name:d->id); d->st_tokens = rrdset_create_localhost( RRD_TYPE_TC , id , name , d->family ? d->family : d->id , RRD_TYPE_TC ".qos_tokens" , "Class Tokens" , "tokens" , PLUGIN_TC_NAME , NULL , NETDATA_CHART_PRIO_TC_QOS_TOCKENS , localhost->rrd_update_every , RRDSET_TYPE_LINE ); } else { rrdset_next(d->st_tokens); if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(name, RRD_ID_LENGTH_MAX, "%s_tokens", d->name?d->name:d->id); rrdset_set_name(d->st_tokens, name); } // TODO // update the family } for(c = d->classes ; c ; c = c->next) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_tokens)) { c->rd_tokens = rrddim_add(d->st_tokens, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_ABSOLUTE); } else if(unlikely(c->name_updated)) rrddim_set_name(d->st_tokens, c->rd_tokens, c->name); rrddim_set_by_pointer(d->st_tokens, c->rd_tokens, c->tokens); } rrdset_done(d->st_tokens); } // -------------------------------------------------------------------- // ctokens if(d->enabled_ctokens == CONFIG_BOOLEAN_YES || (d->enabled_ctokens == CONFIG_BOOLEAN_AUTO && ctokens_sum)) { d->enabled_ctokens = CONFIG_BOOLEAN_YES; if(unlikely(!d->st_ctokens)) { char id[RRD_ID_LENGTH_MAX + 1]; char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(id, RRD_ID_LENGTH_MAX, "%s_ctokens", d->id); snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", d->name?d->name:d->id); d->st_ctokens = rrdset_create_localhost( RRD_TYPE_TC , id , name , d->family ? d->family : d->id , RRD_TYPE_TC ".qos_ctokens" , "Class cTokens" , "ctokens" , PLUGIN_TC_NAME , NULL , NETDATA_CHART_PRIO_TC_QOS_CTOCKENS , localhost->rrd_update_every , RRDSET_TYPE_LINE ); } else { debug(D_TC_LOOP, "TC: Updating _ctokens chart for device '%s'", d->name?d->name:d->id); rrdset_next(d->st_ctokens); if(unlikely(d->name_updated)) { char name[RRD_ID_LENGTH_MAX + 1]; snprintfz(name, RRD_ID_LENGTH_MAX, "%s_ctokens", d->name?d->name:d->id); rrdset_set_name(d->st_ctokens, name); } // TODO // update the family } for(c = d->classes ; c ; c = c->next) { if(unlikely(!c->render)) continue; if(unlikely(!c->rd_ctokens)) c->rd_ctokens = rrddim_add(d->st_ctokens, c->id, c->name?c->name:c->id, 1, 1, RRD_ALGORITHM_ABSOLUTE); else if(unlikely(c->name_updated)) rrddim_set_name(d->st_ctokens, c->rd_ctokens, c->name); rrddim_set_by_pointer(d->st_ctokens, c->rd_ctokens, c->ctokens); } rrdset_done(d->st_ctokens); } tc_device_classes_cleanup(d); }
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; }
int do_proc_meminfo(int update_every, unsigned long long dt) { static procfile *ff = NULL; static int do_ram = -1, do_swap = -1, do_hwcorrupt = -1, do_committed = -1, do_writeback = -1, do_kernel = -1, do_slab = -1; if(do_ram == -1) do_ram = config_get_boolean("plugin:proc:/proc/meminfo", "system ram", 1); if(do_swap == -1) do_swap = config_get_boolean("plugin:proc:/proc/meminfo", "system swap", 1); if(do_hwcorrupt == -1) do_hwcorrupt = config_get_boolean_ondemand("plugin:proc:/proc/meminfo", "hardware corrupted ECC", CONFIG_ONDEMAND_ONDEMAND); if(do_committed == -1) do_committed = config_get_boolean("plugin:proc:/proc/meminfo", "committed memory", 1); if(do_writeback == -1) do_writeback = config_get_boolean("plugin:proc:/proc/meminfo", "writeback memory", 1); if(do_kernel == -1) do_kernel = config_get_boolean("plugin:proc:/proc/meminfo", "kernel memory", 1); if(do_slab == -1) do_slab = config_get_boolean("plugin:proc:/proc/meminfo", "slab memory", 1); if(dt) {}; if(!ff) { char filename[FILENAME_MAX + 1]; snprintf(filename, FILENAME_MAX, "%s%s", global_host_prefix, "/proc/meminfo"); ff = procfile_open(config_get("plugin:proc:/proc/meminfo", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT); } if(!ff) return 1; ff = procfile_readall(ff); if(!ff) return 0; // we return 0, so that we will retry to open it next time uint32_t lines = procfile_lines(ff), l; uint32_t words; int hwcorrupted = 0; unsigned long long MemTotal = 0, MemFree = 0, Buffers = 0, Cached = 0, SwapCached = 0, Active = 0, Inactive = 0, ActiveAnon = 0, InactiveAnon = 0, ActiveFile = 0, InactiveFile = 0, Unevictable = 0, Mlocked = 0, SwapTotal = 0, SwapFree = 0, Dirty = 0, Writeback = 0, AnonPages = 0, Mapped = 0, Shmem = 0, Slab = 0, SReclaimable = 0, SUnreclaim = 0, KernelStack = 0, PageTables = 0, NFS_Unstable = 0, Bounce = 0, WritebackTmp = 0, CommitLimit = 0, Committed_AS = 0, VmallocTotal = 0, VmallocUsed = 0, VmallocChunk = 0, AnonHugePages = 0, HugePages_Total = 0, HugePages_Free = 0, HugePages_Rsvd = 0, HugePages_Surp = 0, Hugepagesize = 0, DirectMap4k = 0, DirectMap2M = 0, HardwareCorrupted = 0; for(l = 0; l < lines ;l++) { words = procfile_linewords(ff, l); if(words < 2) continue; char *name = procfile_lineword(ff, l, 0); unsigned long long value = strtoull(procfile_lineword(ff, l, 1), NULL, 10); if(!MemTotal && strcmp(name, "MemTotal") == 0) MemTotal = value; else if(!MemFree && strcmp(name, "MemFree") == 0) MemFree = value; else if(!Buffers && strcmp(name, "Buffers") == 0) Buffers = value; else if(!Cached && strcmp(name, "Cached") == 0) Cached = value; else if(!SwapCached && strcmp(name, "SwapCached") == 0) SwapCached = value; else if(!Active && strcmp(name, "Active") == 0) Active = value; else if(!Inactive && strcmp(name, "Inactive") == 0) Inactive = value; else if(!ActiveAnon && strcmp(name, "ActiveAnon") == 0) ActiveAnon = value; else if(!InactiveAnon && strcmp(name, "InactiveAnon") == 0) InactiveAnon = value; else if(!ActiveFile && strcmp(name, "ActiveFile") == 0) ActiveFile = value; else if(!InactiveFile && strcmp(name, "InactiveFile") == 0) InactiveFile = value; else if(!Unevictable && strcmp(name, "Unevictable") == 0) Unevictable = value; else if(!Mlocked && strcmp(name, "Mlocked") == 0) Mlocked = value; else if(!SwapTotal && strcmp(name, "SwapTotal") == 0) SwapTotal = value; else if(!SwapFree && strcmp(name, "SwapFree") == 0) SwapFree = value; else if(!Dirty && strcmp(name, "Dirty") == 0) Dirty = value; else if(!Writeback && strcmp(name, "Writeback") == 0) Writeback = value; else if(!AnonPages && strcmp(name, "AnonPages") == 0) AnonPages = value; else if(!Mapped && strcmp(name, "Mapped") == 0) Mapped = value; else if(!Shmem && strcmp(name, "Shmem") == 0) Shmem = value; else if(!Slab && strcmp(name, "Slab") == 0) Slab = value; else if(!SReclaimable && strcmp(name, "SReclaimable") == 0) SReclaimable = value; else if(!SUnreclaim && strcmp(name, "SUnreclaim") == 0) SUnreclaim = value; else if(!KernelStack && strcmp(name, "KernelStack") == 0) KernelStack = value; else if(!PageTables && strcmp(name, "PageTables") == 0) PageTables = value; else if(!NFS_Unstable && strcmp(name, "NFS_Unstable") == 0) NFS_Unstable = value; else if(!Bounce && strcmp(name, "Bounce") == 0) Bounce = value; else if(!WritebackTmp && strcmp(name, "WritebackTmp") == 0) WritebackTmp = value; else if(!CommitLimit && strcmp(name, "CommitLimit") == 0) CommitLimit = value; else if(!Committed_AS && strcmp(name, "Committed_AS") == 0) Committed_AS = value; else if(!VmallocTotal && strcmp(name, "VmallocTotal") == 0) VmallocTotal = value; else if(!VmallocUsed && strcmp(name, "VmallocUsed") == 0) VmallocUsed = value; else if(!VmallocChunk && strcmp(name, "VmallocChunk") == 0) VmallocChunk = value; else if(!HardwareCorrupted && strcmp(name, "HardwareCorrupted") == 0) { HardwareCorrupted = value; hwcorrupted = 1; } else if(!AnonHugePages && strcmp(name, "AnonHugePages") == 0) AnonHugePages = value; else if(!HugePages_Total && strcmp(name, "HugePages_Total") == 0) HugePages_Total = value; else if(!HugePages_Free && strcmp(name, "HugePages_Free") == 0) HugePages_Free = value; else if(!HugePages_Rsvd && strcmp(name, "HugePages_Rsvd") == 0) HugePages_Rsvd = value; else if(!HugePages_Surp && strcmp(name, "HugePages_Surp") == 0) HugePages_Surp = value; else if(!Hugepagesize && strcmp(name, "Hugepagesize") == 0) Hugepagesize = value; else if(!DirectMap4k && strcmp(name, "DirectMap4k") == 0) DirectMap4k = value; else if(!DirectMap2M && strcmp(name, "DirectMap2M") == 0) DirectMap2M = value; } RRDSET *st; // -------------------------------------------------------------------- // http://stackoverflow.com/questions/3019748/how-to-reliably-measure-available-memory-in-linux unsigned long long MemUsed = MemTotal - MemFree - Cached - Buffers; if(do_ram) { st = rrdset_find("system.ram"); if(!st) { st = rrdset_create("system", "ram", NULL, "ram", NULL, "System RAM", "MB", 200, update_every, RRDSET_TYPE_STACKED); rrddim_add(st, "buffers", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "cached", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "used", MemUsed); rrddim_set(st, "free", MemFree); rrddim_set(st, "cached", Cached); rrddim_set(st, "buffers", Buffers); rrdset_done(st); } // -------------------------------------------------------------------- unsigned long long SwapUsed = SwapTotal - SwapFree; if(do_swap) { st = rrdset_find("system.swap"); if(!st) { st = rrdset_create("system", "swap", NULL, "swap", NULL, "System Swap", "MB", 201, update_every, RRDSET_TYPE_STACKED); st->isdetail = 1; rrddim_add(st, "free", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "used", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "used", SwapUsed); rrddim_set(st, "free", SwapFree); rrdset_done(st); } // -------------------------------------------------------------------- if(hwcorrupted && do_hwcorrupt && HardwareCorrupted > 0) { do_hwcorrupt = CONFIG_ONDEMAND_YES; st = rrdset_find("mem.hwcorrupt"); if(!st) { st = rrdset_create("mem", "hwcorrupt", NULL, "errors", NULL, "Hardware Corrupted ECC", "MB", 9000, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "HardwareCorrupted", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "HardwareCorrupted", HardwareCorrupted); rrdset_done(st); } // -------------------------------------------------------------------- if(do_committed) { st = rrdset_find("mem.committed"); if(!st) { st = rrdset_create("mem", "committed", NULL, "system", NULL, "Committed (Allocated) Memory", "MB", 5000, update_every, RRDSET_TYPE_AREA); st->isdetail = 1; rrddim_add(st, "Committed_AS", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "Committed_AS", Committed_AS); rrdset_done(st); } // -------------------------------------------------------------------- if(do_writeback) { st = rrdset_find("mem.writeback"); if(!st) { st = rrdset_create("mem", "writeback", NULL, "kernel", NULL, "Writeback Memory", "MB", 4000, update_every, RRDSET_TYPE_LINE); st->isdetail = 1; rrddim_add(st, "Dirty", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "Writeback", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "FuseWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "NfsWriteback", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "Bounce", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "Dirty", Dirty); rrddim_set(st, "Writeback", Writeback); rrddim_set(st, "FuseWriteback", WritebackTmp); rrddim_set(st, "NfsWriteback", NFS_Unstable); rrddim_set(st, "Bounce", Bounce); rrdset_done(st); } // -------------------------------------------------------------------- if(do_kernel) { st = rrdset_find("mem.kernel"); if(!st) { st = rrdset_create("mem", "kernel", NULL, "kernel", NULL, "Memory Used by Kernel", "MB", 6000, update_every, RRDSET_TYPE_STACKED); st->isdetail = 1; rrddim_add(st, "Slab", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "KernelStack", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "PageTables", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "VmallocUsed", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "KernelStack", KernelStack); rrddim_set(st, "Slab", Slab); rrddim_set(st, "PageTables", PageTables); rrddim_set(st, "VmallocUsed", VmallocUsed); rrdset_done(st); } // -------------------------------------------------------------------- if(do_slab) { st = rrdset_find("mem.slab"); if(!st) { st = rrdset_create("mem", "slab", NULL, "slab", NULL, "Reclaimable Kernel Memory", "MB", 6500, update_every, RRDSET_TYPE_STACKED); st->isdetail = 1; rrddim_add(st, "reclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE); rrddim_add(st, "unreclaimable", NULL, 1, 1024, RRDDIM_ABSOLUTE); } else rrdset_next(st); rrddim_set(st, "reclaimable", SReclaimable); rrddim_set(st, "unreclaimable", SUnreclaim); rrdset_done(st); } return 0; }
int do_getifaddrs(int update_every, usec_t dt) { (void)dt; #define DELAULT_EXLUDED_INTERFACES "lo*" #define CONFIG_SECTION_GETIFADDRS "plugin:freebsd:getifaddrs" static int enable_new_interfaces = -1; static int do_bandwidth_ipv4 = -1, do_bandwidth_ipv6 = -1, do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_events = -1; static SIMPLE_PATTERN *excluded_interfaces = NULL; if (unlikely(enable_new_interfaces == -1)) { enable_new_interfaces = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "enable new interfaces detected at runtime", CONFIG_BOOLEAN_AUTO); do_bandwidth_ipv4 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv4 interfaces", CONFIG_BOOLEAN_AUTO); do_bandwidth_ipv6 = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "total bandwidth for ipv6 interfaces", CONFIG_BOOLEAN_AUTO); do_bandwidth = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "bandwidth for all interfaces", CONFIG_BOOLEAN_AUTO); do_packets = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "packets for all interfaces", CONFIG_BOOLEAN_AUTO); do_errors = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "errors for all interfaces", CONFIG_BOOLEAN_AUTO); do_drops = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "drops for all interfaces", CONFIG_BOOLEAN_AUTO); do_events = config_get_boolean_ondemand(CONFIG_SECTION_GETIFADDRS, "collisions for all interfaces", CONFIG_BOOLEAN_AUTO); excluded_interfaces = simple_pattern_create( config_get(CONFIG_SECTION_GETIFADDRS, "disable by default interfaces matching", DELAULT_EXLUDED_INTERFACES) , NULL , SIMPLE_PATTERN_EXACT ); } if (likely(do_bandwidth_ipv4 || do_bandwidth_ipv6 || do_bandwidth || do_packets || do_errors || do_drops || do_events)) { struct ifaddrs *ifap; if (unlikely(getifaddrs(&ifap))) { error("FREEBSD: getifaddrs() failed"); do_bandwidth_ipv4 = 0; error("DISABLED: system.ipv4 chart"); do_bandwidth_ipv6 = 0; error("DISABLED: system.ipv6 chart"); do_bandwidth = 0; error("DISABLED: net.* charts"); do_packets = 0; error("DISABLED: net_packets.* charts"); do_errors = 0; error("DISABLED: net_errors.* charts"); do_drops = 0; error("DISABLED: net_drops.* charts"); do_events = 0; error("DISABLED: net_events.* charts"); error("DISABLED: getifaddrs module"); return 1; } else { #define IFA_DATA(s) (((struct if_data *)ifa->ifa_data)->ifi_ ## s) struct ifaddrs *ifa; struct iftot { u_long ift_ibytes; u_long ift_obytes; } iftot = {0, 0}; // -------------------------------------------------------------------- if (likely(do_bandwidth_ipv4)) { iftot.ift_ibytes = iftot.ift_obytes = 0; for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != AF_INET) continue; iftot.ift_ibytes += IFA_DATA(ibytes); iftot.ift_obytes += IFA_DATA(obytes); } static RRDSET *st = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; if (unlikely(!st)) { st = rrdset_create_localhost("system", "ipv4", NULL, "network", NULL, "IPv4 Bandwidth", "kilobits/s", "freebsd", "getifaddrs", 500, update_every, RRDSET_TYPE_AREA ); rd_in = rrddim_add(st, "InOctets", "received", 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "OutOctets", "sent", -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes); rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes); rrdset_done(st); } // -------------------------------------------------------------------- if (likely(do_bandwidth_ipv6)) { iftot.ift_ibytes = iftot.ift_obytes = 0; for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; iftot.ift_ibytes += IFA_DATA(ibytes); iftot.ift_obytes += IFA_DATA(obytes); } static RRDSET *st = NULL; static RRDDIM *rd_in = NULL, *rd_out = NULL; if (unlikely(!st)) { st = rrdset_create_localhost("system", "ipv6", NULL, "network", NULL, "IPv6 Bandwidth", "kilobits/s", "freebsd", "getifaddrs", 500, update_every, RRDSET_TYPE_AREA ); rd_in = rrddim_add(st, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); rd_out = rrddim_add(st, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(st); rrddim_set_by_pointer(st, rd_in, iftot.ift_ibytes); rrddim_set_by_pointer(st, rd_out, iftot.ift_obytes); rrdset_done(st); } // -------------------------------------------------------------------- network_interfaces_found = 0; for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != AF_LINK) continue; struct cgroup_network_interface *ifm = get_network_interface(ifa->ifa_name); ifm->updated = 1; network_interfaces_found++; if (unlikely(!ifm->configured)) { char var_name[4096 + 1]; // this is the first time we see this network interface // remember we configured it ifm->configured = 1; ifm->enabled = enable_new_interfaces; if (likely(ifm->enabled)) ifm->enabled = !simple_pattern_matches(excluded_interfaces, ifa->ifa_name); snprintfz(var_name, 4096, "%s:%s", CONFIG_SECTION_GETIFADDRS, ifa->ifa_name); ifm->enabled = config_get_boolean_ondemand(var_name, "enabled", ifm->enabled); if (unlikely(ifm->enabled == CONFIG_BOOLEAN_NO)) continue; ifm->do_bandwidth = config_get_boolean_ondemand(var_name, "bandwidth", do_bandwidth); ifm->do_packets = config_get_boolean_ondemand(var_name, "packets", do_packets); ifm->do_errors = config_get_boolean_ondemand(var_name, "errors", do_errors); ifm->do_drops = config_get_boolean_ondemand(var_name, "drops", do_drops); ifm->do_events = config_get_boolean_ondemand(var_name, "events", do_events); } if (unlikely(!ifm->enabled)) continue; // -------------------------------------------------------------------- if (ifm->do_bandwidth == CONFIG_BOOLEAN_YES || (ifm->do_bandwidth == CONFIG_BOOLEAN_AUTO && (IFA_DATA(ibytes) || IFA_DATA(obytes)))) { if (unlikely(!ifm->st_bandwidth)) { ifm->st_bandwidth = rrdset_create_localhost("net", ifa->ifa_name, NULL, ifa->ifa_name, "net.net", "Bandwidth", "kilobits/s", "freebsd", "getifaddrs", 7000, update_every, RRDSET_TYPE_AREA ); ifm->rd_bandwidth_in = rrddim_add(ifm->st_bandwidth, "received", NULL, 8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); ifm->rd_bandwidth_out = rrddim_add(ifm->st_bandwidth, "sent", NULL, -8, BITS_IN_A_KILOBIT, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(ifm->st_bandwidth); rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_in, IFA_DATA(ibytes)); rrddim_set_by_pointer(ifm->st_bandwidth, ifm->rd_bandwidth_out, IFA_DATA(obytes)); rrdset_done(ifm->st_bandwidth); } // -------------------------------------------------------------------- if (ifm->do_packets == CONFIG_BOOLEAN_YES || (ifm->do_packets == CONFIG_BOOLEAN_AUTO && (IFA_DATA(ipackets) || IFA_DATA(opackets) || IFA_DATA(imcasts) || IFA_DATA(omcasts)))) { if (unlikely(!ifm->st_packets)) { ifm->st_packets = rrdset_create_localhost("net_packets", ifa->ifa_name, NULL, ifa->ifa_name, "net.packets", "Packets", "packets/s", "freebsd", "getifaddrs", 7001, update_every, RRDSET_TYPE_LINE ); rrdset_flag_set(ifm->st_packets, RRDSET_FLAG_DETAIL); ifm->rd_packets_in = rrddim_add(ifm->st_packets, "received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); ifm->rd_packets_out = rrddim_add(ifm->st_packets, "sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); ifm->rd_packets_m_in = rrddim_add(ifm->st_packets, "multicast_received", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); ifm->rd_packets_m_out = rrddim_add(ifm->st_packets, "multicast_sent", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(ifm->st_packets); rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_in, IFA_DATA(ipackets)); rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_out, IFA_DATA(opackets)); rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_in, IFA_DATA(imcasts)); rrddim_set_by_pointer(ifm->st_packets, ifm->rd_packets_m_out, IFA_DATA(omcasts)); rrdset_done(ifm->st_packets); } // -------------------------------------------------------------------- if (ifm->do_errors == CONFIG_BOOLEAN_YES || (ifm->do_errors == CONFIG_BOOLEAN_AUTO && (IFA_DATA(ierrors) || IFA_DATA(oerrors)))) { if (unlikely(!ifm->st_errors)) { ifm->st_errors = rrdset_create_localhost("net_errors", ifa->ifa_name, NULL, ifa->ifa_name, "net.errors", "Interface Errors", "errors/s", "freebsd", "getifaddrs", 7002, update_every, RRDSET_TYPE_LINE ); rrdset_flag_set(ifm->st_errors, RRDSET_FLAG_DETAIL); ifm->rd_errors_in = rrddim_add(ifm->st_errors, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); ifm->rd_errors_out = rrddim_add(ifm->st_errors, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(ifm->st_errors); rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_in, IFA_DATA(ierrors)); rrddim_set_by_pointer(ifm->st_errors, ifm->rd_errors_out, IFA_DATA(oerrors)); rrdset_done(ifm->st_errors); } // -------------------------------------------------------------------- if (ifm->do_drops == CONFIG_BOOLEAN_YES || (ifm->do_drops == CONFIG_BOOLEAN_AUTO && (IFA_DATA(iqdrops) #if __FreeBSD__ >= 11 || IFA_DATA(oqdrops) #endif ))) { if (unlikely(!ifm->st_drops)) { ifm->st_drops = rrdset_create_localhost("net_drops", ifa->ifa_name, NULL, ifa->ifa_name, "net.drops", "Interface Drops", "drops/s", "freebsd", "getifaddrs", 7003, update_every, RRDSET_TYPE_LINE ); rrdset_flag_set(ifm->st_drops, RRDSET_FLAG_DETAIL); ifm->rd_drops_in = rrddim_add(ifm->st_drops, "inbound", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); #if __FreeBSD__ >= 11 ifm->rd_drops_out = rrddim_add(ifm->st_drops, "outbound", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); #endif } else rrdset_next(ifm->st_drops); rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_in, IFA_DATA(iqdrops)); #if __FreeBSD__ >= 11 rrddim_set_by_pointer(ifm->st_drops, ifm->rd_drops_out, IFA_DATA(oqdrops)); #endif rrdset_done(ifm->st_drops); } // -------------------------------------------------------------------- if (ifm->do_events == CONFIG_BOOLEAN_YES || (ifm->do_events == CONFIG_BOOLEAN_AUTO && IFA_DATA(collisions))) { if (unlikely(!ifm->st_events)) { ifm->st_events = rrdset_create_localhost("net_events", ifa->ifa_name, NULL, ifa->ifa_name, "net.events", "Network Interface Events", "events/s", "freebsd", "getifaddrs", 7006, update_every, RRDSET_TYPE_LINE ); rrdset_flag_set(ifm->st_events, RRDSET_FLAG_DETAIL); ifm->rd_events_coll = rrddim_add(ifm->st_events, "collisions", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL); } else rrdset_next(ifm->st_events); rrddim_set_by_pointer(ifm->st_events, ifm->rd_events_coll, IFA_DATA(collisions)); rrdset_done(ifm->st_events); } } freeifaddrs(ifap); } } else { error("DISABLED: getifaddrs module"); return 1; } network_interfaces_cleanup(); return 0; }