diff options
Diffstat (limited to 'collectors/cgroups.plugin')
-rw-r--r-- | collectors/cgroups.plugin/README.md | 12 | ||||
-rw-r--r-- | collectors/cgroups.plugin/cgroup-network.c | 81 | ||||
-rw-r--r-- | collectors/cgroups.plugin/sys_fs_cgroup.c | 184 |
3 files changed, 128 insertions, 149 deletions
diff --git a/collectors/cgroups.plugin/README.md b/collectors/cgroups.plugin/README.md index d0f822e66..e58f1ba04 100644 --- a/collectors/cgroups.plugin/README.md +++ b/collectors/cgroups.plugin/README.md @@ -1,6 +1,10 @@ <!-- -title: "cgroups.plugin" -custom_edit_url: https://github.com/netdata/netdata/edit/master/collectors/cgroups.plugin/README.md +title: "Monitor Cgroups (cgroups.plugin)" +custom_edit_url: "https://github.com/netdata/netdata/edit/master/collectors/cgroups.plugin/README.md" +sidebar_label: "Monitor Cgroups" +learn_status: "Published" +learn_topic_type: "References" +learn_rel_path: "References/Collectors references/Virtualized environments/Containers" --> # cgroups.plugin @@ -74,7 +78,7 @@ currently unsupported when using unified cgroups. ### enabled cgroups To provide a sane default, Netdata uses the -following [pattern list](https://learn.netdata.cloud/docs/agent/libnetdata/simple_pattern): +following [pattern list](https://github.com/netdata/netdata/blob/master/libnetdata/simple_pattern/README.md): - checks the pattern against the path of the cgroup @@ -305,4 +309,4 @@ cannot find, but immediately: - I/O full pressure Network interfaces are monitored by means of -the [proc plugin](/collectors/proc.plugin/README.md#monitored-network-interface-metrics). +the [proc plugin](https://github.com/netdata/netdata/blob/master/collectors/proc.plugin/README.md#monitored-network-interface-metrics). diff --git a/collectors/cgroups.plugin/cgroup-network.c b/collectors/cgroups.plugin/cgroup-network.c index 0b66ea475..a490df394 100644 --- a/collectors/cgroups.plugin/cgroup-network.c +++ b/collectors/cgroups.plugin/cgroup-network.c @@ -43,7 +43,7 @@ unsigned int read_iface_iflink(const char *prefix, const char *iface) { unsigned long long iflink = 0; int ret = read_single_number_file(filename, &iflink); - if(ret) error("Cannot read '%s'.", filename); + if(ret) collector_error("Cannot read '%s'.", filename); return (unsigned int)iflink; } @@ -56,7 +56,7 @@ unsigned int read_iface_ifindex(const char *prefix, const char *iface) { unsigned long long ifindex = 0; int ret = read_single_number_file(filename, &ifindex); - if(ret) error("Cannot read '%s'.", filename); + if(ret) collector_error("Cannot read '%s'.", filename); return (unsigned int)ifindex; } @@ -70,18 +70,18 @@ struct iface *read_proc_net_dev(const char *scope __maybe_unused, const char *pr snprintfz(filename, FILENAME_MAX, "%s%s", prefix, (*prefix)?"/proc/1/net/dev":"/proc/net/dev"); #ifdef NETDATA_INTERNAL_CHECKS - info("parsing '%s'", filename); + collector_info("parsing '%s'", filename); #endif ff = procfile_open(filename, " \t,:|", PROCFILE_FLAG_DEFAULT); if(unlikely(!ff)) { - error("Cannot open file '%s'", filename); + collector_error("Cannot open file '%s'", filename); return NULL; } ff = procfile_readall(ff); if(unlikely(!ff)) { - error("Cannot read file '%s'", filename); + collector_error("Cannot read file '%s'", filename); return NULL; } @@ -99,7 +99,7 @@ struct iface *read_proc_net_dev(const char *scope __maybe_unused, const char *pr root = t; #ifdef NETDATA_INTERNAL_CHECKS - info("added %s interface '%s', ifindex %u, iflink %u", scope, t->device, t->ifindex, t->iflink); + collector_info("added %s interface '%s', ifindex %u, iflink %u", scope, t->device, t->ifindex, t->iflink); #endif } @@ -145,7 +145,7 @@ static void continue_as_child(void) { pid_t ret; if (child < 0) - error("fork() failed"); + collector_error("fork() failed"); /* Only the child returns */ if (child == 0) @@ -180,7 +180,7 @@ int proc_pid_fd(const char *prefix, const char *ns, pid_t pid) { int fd = open(filename, O_RDONLY); if(fd == -1) - error("Cannot open proc_pid_fd() file '%s'", filename); + collector_error("Cannot open proc_pid_fd() file '%s'", filename); return fd; } @@ -230,7 +230,7 @@ int switch_namespace(const char *prefix, pid_t pid) { if(setns(all_ns[i].fd, all_ns[i].nstype) == -1) { if(pass == 1) { all_ns[i].status = 0; - error("Cannot switch to %s namespace of pid %d", all_ns[i].name, (int) pid); + collector_error("Cannot switch to %s namespace of pid %d", all_ns[i].name, (int) pid); } } else @@ -243,17 +243,17 @@ int switch_namespace(const char *prefix, pid_t pid) { if(root_fd != -1) { if(fchdir(root_fd) < 0) - error("Cannot fchdir() to pid %d root directory", (int)pid); + collector_error("Cannot fchdir() to pid %d root directory", (int)pid); if(chroot(".") < 0) - error("Cannot chroot() to pid %d root directory", (int)pid); + collector_error("Cannot chroot() to pid %d root directory", (int)pid); close(root_fd); } if(cwd_fd != -1) { if(fchdir(cwd_fd) < 0) - error("Cannot fchdir() to pid %d current working directory", (int)pid); + collector_error("Cannot fchdir() to pid %d current working directory", (int)pid); close(cwd_fd); } @@ -277,7 +277,7 @@ int switch_namespace(const char *prefix, pid_t pid) { #else errno = ENOSYS; - error("setns() is missing on this system."); + collector_error("setns() is missing on this system."); return 1; #endif @@ -286,13 +286,13 @@ int switch_namespace(const char *prefix, pid_t pid) { pid_t read_pid_from_cgroup_file(const char *filename) { int fd = open(filename, procfile_open_flags); if(fd == -1) { - error("Cannot open pid_from_cgroup() file '%s'.", filename); + collector_error("Cannot open pid_from_cgroup() file '%s'.", filename); return 0; } FILE *fp = fdopen(fd, "r"); if(!fp) { - error("Cannot upgrade fd to fp for file '%s'.", filename); + collector_error("Cannot upgrade fd to fp for file '%s'.", filename); return 0; } @@ -308,7 +308,7 @@ pid_t read_pid_from_cgroup_file(const char *filename) { fclose(fp); #ifdef NETDATA_INTERNAL_CHECKS - if(pid > 0) info("found pid %d on file '%s'", pid, filename); + if(pid > 0) collector_info("found pid %d on file '%s'", pid, filename); #endif return pid; @@ -331,7 +331,7 @@ pid_t read_pid_from_cgroup(const char *path) { DIR *dir = opendir(path); if (!dir) { - error("cannot read directory '%s'", path); + collector_error("cannot read directory '%s'", path); return 0; } @@ -369,7 +369,7 @@ struct found_device { void add_device(const char *host, const char *guest) { #ifdef NETDATA_INTERNAL_CHECKS - info("adding device with host '%s', guest '%s'", host, guest); + collector_info("adding device with host '%s', guest '%s'", host, guest); #endif uint32_t hash = simple_hash(host); @@ -422,36 +422,36 @@ void detect_veth_interfaces(pid_t pid) { host = read_proc_net_dev("host", netdata_configured_host_prefix); if(!host) { errno = 0; - error("cannot read host interface list."); + collector_error("cannot read host interface list."); goto cleanup; } if(!eligible_ifaces(host)) { errno = 0; - info("there are no double-linked host interfaces available."); + collector_info("there are no double-linked host interfaces available."); goto cleanup; } if(switch_namespace(netdata_configured_host_prefix, pid)) { errno = 0; - error("cannot switch to the namespace of pid %u", (unsigned int) pid); + collector_error("cannot switch to the namespace of pid %u", (unsigned int) pid); goto cleanup; } #ifdef NETDATA_INTERNAL_CHECKS - info("switched to namespaces of pid %d", pid); + collector_info("switched to namespaces of pid %d", pid); #endif cgroup = read_proc_net_dev("cgroup", NULL); if(!cgroup) { errno = 0; - error("cannot read cgroup interface list."); + collector_error("cannot read cgroup interface list."); goto cleanup; } if(!eligible_ifaces(cgroup)) { errno = 0; - error("there are not double-linked cgroup interfaces available."); + collector_error("there are not double-linked cgroup interfaces available."); goto cleanup; } @@ -495,7 +495,7 @@ cleanup: #define CGROUP_NETWORK_INTERFACE_MAX_LINE 2048 void call_the_helper(pid_t pid, const char *cgroup) { if(setresuid(0, 0, 0) == -1) - error("setresuid(0, 0, 0) failed."); + collector_error("setresuid(0, 0, 0) failed."); char command[CGROUP_NETWORK_INTERFACE_MAX_LINE + 1]; if(cgroup) @@ -503,7 +503,7 @@ void call_the_helper(pid_t pid, const char *cgroup) { else snprintfz(command, CGROUP_NETWORK_INTERFACE_MAX_LINE, "exec " PLUGINS_DIR "/cgroup-network-helper.sh --pid %d", pid); - info("running: %s", command); + collector_info("running: %s", command); pid_t cgroup_pid; FILE *fp_child_input, *fp_child_output; @@ -539,7 +539,7 @@ void call_the_helper(pid_t pid, const char *cgroup) { netdata_pclose(fp_child_input, fp_child_output, cgroup_pid); } else - error("cannot execute cgroup-network helper script: %s", command); + collector_error("cannot execute cgroup-network helper script: %s", command); } int is_valid_path_symbol(char c) { @@ -570,33 +570,33 @@ int verify_path(const char *path) { const char *s = path; while((c = *s++)) { if(!( isalnum(c) || is_valid_path_symbol(c) )) { - error("invalid character in path '%s'", path); + collector_error("invalid character in path '%s'", path); return -1; } } if(strstr(path, "\\") && !strstr(path, "\\x")) { - error("invalid escape sequence in path '%s'", path); + collector_error("invalid escape sequence in path '%s'", path); return 1; } if(strstr(path, "/../")) { - error("invalid parent path sequence detected in '%s'", path); + collector_error("invalid parent path sequence detected in '%s'", path); return 1; } if(path[0] != '/') { - error("only absolute path names are supported - invalid path '%s'", path); + collector_error("only absolute path names are supported - invalid path '%s'", path); return -1; } if (stat(path, &sb) == -1) { - error("cannot stat() path '%s'", path); + collector_error("cannot stat() path '%s'", path); return -1; } if((sb.st_mode & S_IFMT) != S_IFDIR) { - error("path '%s' is not a directory", path); + collector_error("path '%s' is not a directory", path); return -1; } @@ -618,10 +618,10 @@ char *fix_path_variable(void) { char *s = strsep(&ptr, ":"); if(s && *s) { if(verify_path(s) == -1) { - error("the PATH variable includes an invalid path '%s' - removed it.", s); + collector_error("the PATH variable includes an invalid path '%s' - removed it.", s); } else { - info("the PATH variable includes a valid path '%s'.", s); + collector_info("the PATH variable includes a valid path '%s'.", s); if(added) strcat(safe_path, ":"); strcat(safe_path, s); added++; @@ -629,8 +629,8 @@ char *fix_path_variable(void) { } } - info("unsafe PATH: '%s'.", path); - info(" safe PATH: '%s'.", safe_path); + collector_info("unsafe PATH: '%s'.", path); + collector_info(" safe PATH: '%s'.", safe_path); freez(p); return safe_path; @@ -646,6 +646,7 @@ void usage(void) { } int main(int argc, char **argv) { + stderror = stderr; pid_t pid = 0; program_name = argv[0]; @@ -690,7 +691,7 @@ int main(int argc, char **argv) { if(pid <= 0) { errno = 0; - error("Invalid pid %d given", (int) pid); + collector_error("Invalid pid %d given", (int) pid); return 2; } @@ -699,7 +700,7 @@ int main(int argc, char **argv) { else if(!strcmp(argv[arg], "--cgroup")) { char *cgroup = argv[arg+1]; if(verify_path(cgroup) == -1) { - error("cgroup '%s' does not exist or is not valid.", cgroup); + collector_error("cgroup '%s' does not exist or is not valid.", cgroup); return 1; } @@ -708,7 +709,7 @@ int main(int argc, char **argv) { if(pid <= 0 && !detected_devices) { errno = 0; - error("Cannot find a cgroup PID from cgroup '%s'", cgroup); + collector_error("Cannot find a cgroup PID from cgroup '%s'", cgroup); } } else diff --git a/collectors/cgroups.plugin/sys_fs_cgroup.c b/collectors/cgroups.plugin/sys_fs_cgroup.c index 8f7548286..66db0b728 100644 --- a/collectors/cgroups.plugin/sys_fs_cgroup.c +++ b/collectors/cgroups.plugin/sys_fs_cgroup.c @@ -174,9 +174,9 @@ static enum cgroups_systemd_setting cgroups_detect_systemd(const char *exec) } if (ret == -1) { - error("Failed to get the output of \"%s\"", exec); + collector_error("Failed to get the output of \"%s\"", exec); } else if (ret == 0) { - info("Cannot get the output of \"%s\" within %"PRId64" seconds", exec, (int64_t)timeout.tv_sec); + collector_info("Cannot get the output of \"%s\" within %"PRId64" seconds", exec, (int64_t)timeout.tv_sec); } else { while (fgets(buf, MAXSIZE_PROC_CMDLINE, fp_child_output) != NULL) { if ((begin = strstr(buf, SYSTEMD_HIERARCHY_STRING))) { @@ -214,7 +214,7 @@ static enum cgroups_type cgroups_try_detect_version() FILE *fp_child_input; FILE *fp_child_output = netdata_popen("grep cgroup /proc/filesystems", &command_pid, &fp_child_input); if (!fp_child_output) { - error("popen failed"); + collector_error("popen failed"); return CGROUPS_AUTODETECT_FAIL; } while (fgets(buf, MAXSIZE_PROC_CMDLINE, fp_child_output) != NULL) { @@ -258,12 +258,12 @@ static enum cgroups_type cgroups_try_detect_version() // check kernel command line flag that can override that setting FILE *fp = fopen("/proc/cmdline", "r"); if (!fp) { - error("Error reading kernel boot commandline parameters"); + collector_error("Error reading kernel boot commandline parameters"); return CGROUPS_AUTODETECT_FAIL; } if (!fgets(buf, MAXSIZE_PROC_CMDLINE, fp)) { - error("couldn't read all cmdline params into buffer"); + collector_error("couldn't read all cmdline params into buffer"); fclose(fp); return CGROUPS_AUTODETECT_FAIL; } @@ -271,7 +271,7 @@ static enum cgroups_type cgroups_try_detect_version() fclose(fp); if (strstr(buf, "systemd.unified_cgroup_hierarchy=0")) { - info("cgroups v2 (unified cgroups) is available but are disabled on this system."); + collector_info("cgroups v2 (unified cgroups) is available but are disabled on this system."); return CGROUPS_V1; } return CGROUPS_V2; @@ -311,7 +311,7 @@ void read_cgroup_plugin_configuration() { if(cgroup_use_unified_cgroups == CONFIG_BOOLEAN_AUTO) cgroup_use_unified_cgroups = (cgroups_try_detect_version() == CGROUPS_V2); - info("use unified cgroups %s", cgroup_use_unified_cgroups ? "true" : "false"); + collector_info("use unified cgroups %s", cgroup_use_unified_cgroups ? "true" : "false"); cgroup_containers_chart_priority = (int)config_get_number("plugin:cgroups", "containers priority", cgroup_containers_chart_priority); if(cgroup_containers_chart_priority < 1) @@ -361,7 +361,7 @@ void read_cgroup_plugin_configuration() { mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "cpuacct"); if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "cpuacct"); if(!mi) { - error("CGROUP: cannot find cpuacct mountinfo. Assuming default: /sys/fs/cgroup/cpuacct"); + collector_error("CGROUP: cannot find cpuacct mountinfo. Assuming default: /sys/fs/cgroup/cpuacct"); s = "/sys/fs/cgroup/cpuacct"; } else s = mi->mount_point; @@ -371,7 +371,7 @@ void read_cgroup_plugin_configuration() { mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "cpuset"); if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "cpuset"); if(!mi) { - error("CGROUP: cannot find cpuset mountinfo. Assuming default: /sys/fs/cgroup/cpuset"); + collector_error("CGROUP: cannot find cpuset mountinfo. Assuming default: /sys/fs/cgroup/cpuset"); s = "/sys/fs/cgroup/cpuset"; } else s = mi->mount_point; @@ -381,7 +381,7 @@ void read_cgroup_plugin_configuration() { mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "blkio"); if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "blkio"); if(!mi) { - error("CGROUP: cannot find blkio mountinfo. Assuming default: /sys/fs/cgroup/blkio"); + collector_error("CGROUP: cannot find blkio mountinfo. Assuming default: /sys/fs/cgroup/blkio"); s = "/sys/fs/cgroup/blkio"; } else s = mi->mount_point; @@ -391,7 +391,7 @@ void read_cgroup_plugin_configuration() { mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "memory"); if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "memory"); if(!mi) { - error("CGROUP: cannot find memory mountinfo. Assuming default: /sys/fs/cgroup/memory"); + collector_error("CGROUP: cannot find memory mountinfo. Assuming default: /sys/fs/cgroup/memory"); s = "/sys/fs/cgroup/memory"; } else s = mi->mount_point; @@ -401,7 +401,7 @@ void read_cgroup_plugin_configuration() { mi = mountinfo_find_by_filesystem_super_option(root, "cgroup", "devices"); if(!mi) mi = mountinfo_find_by_filesystem_mount_source(root, "cgroup", "devices"); if(!mi) { - error("CGROUP: cannot find devices mountinfo. Assuming default: /sys/fs/cgroup/devices"); + collector_error("CGROUP: cannot find devices mountinfo. Assuming default: /sys/fs/cgroup/devices"); s = "/sys/fs/cgroup/devices"; } else s = mi->mount_point; @@ -433,7 +433,7 @@ void read_cgroup_plugin_configuration() { if(mi) debug(D_CGROUP, "found unified cgroup root using mountsource info, with path: '%s'", mi->mount_point); } if(!mi) { - error("CGROUP: cannot find cgroup2 mountinfo. Assuming default: /sys/fs/cgroup"); + collector_error("CGROUP: cannot find cgroup2 mountinfo. Assuming default: /sys/fs/cgroup"); s = "/sys/fs/cgroup"; } else s = mi->mount_point; @@ -575,13 +575,13 @@ void netdata_cgroup_ebpf_initialize_shm() { shm_fd_cgroup_ebpf = shm_open(NETDATA_SHARED_MEMORY_EBPF_CGROUP_NAME, O_CREAT | O_RDWR, 0660); if (shm_fd_cgroup_ebpf < 0) { - error("Cannot initialize shared memory used by cgroup and eBPF, integration won't happen."); + collector_error("Cannot initialize shared memory used by cgroup and eBPF, integration won't happen."); return; } size_t length = sizeof(netdata_ebpf_cgroup_shm_header_t) + cgroup_root_max * sizeof(netdata_ebpf_cgroup_shm_body_t); if (ftruncate(shm_fd_cgroup_ebpf, length)) { - error("Cannot set size for shared memory."); + collector_error("Cannot set size for shared memory."); goto end_init_shm; } @@ -590,7 +590,7 @@ void netdata_cgroup_ebpf_initialize_shm() shm_fd_cgroup_ebpf, 0); if (!shm_cgroup_ebpf.header) { - error("Cannot map shared memory used between cgroup and eBPF, integration won't happen"); + collector_error("Cannot map shared memory used between cgroup and eBPF, integration won't happen"); goto end_init_shm; } shm_cgroup_ebpf.body = (netdata_ebpf_cgroup_shm_body_t *) ((char *)shm_cgroup_ebpf.header + @@ -604,7 +604,7 @@ void netdata_cgroup_ebpf_initialize_shm() return; } - error("Cannot create semaphore, integration between eBPF and cgroup won't happen"); + collector_error("Cannot create semaphore, integration between eBPF and cgroup won't happen"); munmap(shm_cgroup_ebpf.header, length); end_init_shm: @@ -1077,7 +1077,7 @@ static inline void cgroup_read_cpuacct_stat(struct cpuacct_stat *cp) { unsigned long i, lines = procfile_lines(ff); if(unlikely(lines < 1)) { - error("CGROUP: file '%s' should have 1+ lines.", cp->filename); + collector_error("CGROUP: file '%s' should have 1+ lines.", cp->filename); cp->updated = 0; return; } @@ -1123,7 +1123,7 @@ static inline void cgroup_read_cpuacct_cpu_stat(struct cpuacct_cpu_throttling *c unsigned long lines = procfile_lines(ff); if (unlikely(lines < 3)) { - error("CGROUP: file '%s' should have 3 lines.", cp->filename); + collector_error("CGROUP: file '%s' should have 3 lines.", cp->filename); cp->updated = 0; return; } @@ -1180,7 +1180,7 @@ static inline void cgroup2_read_cpuacct_cpu_stat(struct cpuacct_stat *cp, struct unsigned long lines = procfile_lines(ff); if (unlikely(lines < 3)) { - error("CGROUP: file '%s' should have at least 3 lines.", cp->filename); + collector_error("CGROUP: file '%s' should have at least 3 lines.", cp->filename); cp->updated = 0; return; } @@ -1261,7 +1261,7 @@ static inline void cgroup_read_cpuacct_usage(struct cpuacct_usage *ca) { } if(unlikely(procfile_lines(ff) < 1)) { - error("CGROUP: file '%s' should have 1+ lines but has %zu.", ca->filename, procfile_lines(ff)); + collector_error("CGROUP: file '%s' should have 1+ lines but has %zu.", ca->filename, procfile_lines(ff)); ca->updated = 0; return; } @@ -1326,7 +1326,7 @@ static inline void cgroup_read_blkio(struct blkio *io) { unsigned long i, lines = procfile_lines(ff); if(unlikely(lines < 1)) { - error("CGROUP: file '%s' should have 1+ lines.", io->filename); + collector_error("CGROUP: file '%s' should have 1+ lines.", io->filename); io->updated = 0; return; } @@ -1398,7 +1398,7 @@ static inline void cgroup2_read_blkio(struct blkio *io, unsigned int word_offset unsigned long i, lines = procfile_lines(ff); if (unlikely(lines < 1)) { - error("CGROUP: file '%s' should have 1+ lines.", io->filename); + collector_error("CGROUP: file '%s' should have 1+ lines.", io->filename); io->updated = 0; return; } @@ -1442,7 +1442,7 @@ static inline void cgroup2_read_pressure(struct pressure *res) { size_t lines = procfile_lines(ff); if (lines < 1) { - error("CGROUP: file '%s' should have 1+ lines.", res->filename); + collector_error("CGROUP: file '%s' should have 1+ lines.", res->filename); res->updated = 0; return; } @@ -1456,7 +1456,7 @@ static inline void cgroup2_read_pressure(struct pressure *res) { res->full.share_time.value10 = strtod(procfile_lineword(ff, 1, 2), NULL); res->full.share_time.value60 = strtod(procfile_lineword(ff, 1, 4), NULL); res->full.share_time.value300 = strtod(procfile_lineword(ff, 1, 6), NULL); - res->full.total_time.value_total = str2ull(procfile_lineword(ff, 0, 8)) / 1000; // us->ms + res->full.total_time.value_total = str2ull(procfile_lineword(ff, 1, 8)) / 1000; // us->ms } res->updated = 1; @@ -1499,7 +1499,7 @@ static inline void cgroup_read_memory(struct memory *mem, char parent_cg_is_unif unsigned long i, lines = procfile_lines(ff); if(unlikely(lines < 1)) { - error("CGROUP: file '%s' should have 1+ lines.", mem->filename_detailed); + collector_error("CGROUP: file '%s' should have 1+ lines.", mem->filename_detailed); mem->updated_detailed = 0; goto memory_next; } @@ -1669,7 +1669,7 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) { FILE *fp_child_input, *fp_child_output; (void)netdata_popen_raw_default_flags_and_environment(&cgroup_pid, &fp_child_input, &fp_child_output, cgroups_network_interface_script, "--cgroup", cgroup_identifier); if(!fp_child_output) { - error("CGROUP: cannot popen(%s --cgroup \"%s\", \"r\").", cgroups_network_interface_script, cgroup_identifier); + collector_error("CGROUP: cannot popen(%s --cgroup \"%s\", \"r\").", cgroups_network_interface_script, cgroup_identifier); return; } @@ -1687,12 +1687,12 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) { } if(!*s) { - error("CGROUP: empty host interface returned by script"); + collector_error("CGROUP: empty host interface returned by script"); continue; } if(!*t) { - error("CGROUP: empty guest interface returned by script"); + collector_error("CGROUP: empty guest interface returned by script"); continue; } @@ -1702,7 +1702,7 @@ static inline void read_cgroup_network_interfaces(struct cgroup *cg) { i->next = cg->interfaces; cg->interfaces = i; - info("CGROUP: cgroup '%s' has network interface '%s' as '%s'", cg->id, i->host_device, i->container_device); + collector_info("CGROUP: cgroup '%s' has network interface '%s' as '%s'", cg->id, i->host_device, i->container_device); // register a device rename to proc_net_dev.c netdev_rename_device_add( @@ -1875,7 +1875,7 @@ static inline void discovery_rename_cgroup(struct cgroup *cg) { FILE *fp_child_input, *fp_child_output; (void)netdata_popen_raw_default_flags_and_environment(&cgroup_pid, &fp_child_input, &fp_child_output, cgroups_rename_script, cg->id, cg->intermediate_id); if (!fp_child_output) { - error("CGROUP: cannot popen(%s \"%s\", \"r\").", cgroups_rename_script, cg->intermediate_id); + collector_error("CGROUP: cannot popen(%s \"%s\", \"r\").", cgroups_rename_script, cg->intermediate_id); cg->pending_renames = 0; cg->processed = 1; return; @@ -2034,14 +2034,14 @@ static inline void discovery_find_cgroup_in_dir_callback(const char *dir) { } if (cgroup_root_count >= cgroup_root_max) { - info("CGROUP: maximum number of cgroups reached (%d). Not adding cgroup '%s'", cgroup_root_count, dir); + collector_info("CGROUP: maximum number of cgroups reached (%d). Not adding cgroup '%s'", cgroup_root_count, dir); return; } if (cgroup_max_depth > 0) { int depth = calc_cgroup_depth(dir); if (depth > cgroup_max_depth) { - info("CGROUP: '%s' is too deep (%d, while max is %d)", dir, depth, cgroup_max_depth); + collector_info("CGROUP: '%s' is too deep (%d, while max is %d)", dir, depth, cgroup_max_depth); return; } } @@ -2066,7 +2066,7 @@ static inline int discovery_find_dir_in_subdirs(const char *base, const char *th DIR *dir = opendir(this); if(!dir) { - error("CGROUP: cannot read directory '%s'", base); + collector_error("CGROUP: cannot read directory '%s'", base); return ret; } ret = 1; @@ -2550,7 +2550,7 @@ static inline void discovery_find_all_cgroups_v1() { if (cgroup_enable_cpuacct_stat || cgroup_enable_cpuacct_usage) { if (discovery_find_dir_in_subdirs(cgroup_cpuacct_base, NULL, discovery_find_cgroup_in_dir_callback) == -1) { cgroup_enable_cpuacct_stat = cgroup_enable_cpuacct_usage = CONFIG_BOOLEAN_NO; - error("CGROUP: disabled cpu statistics."); + collector_error("CGROUP: disabled cpu statistics."); } } @@ -2560,7 +2560,7 @@ static inline void discovery_find_all_cgroups_v1() { cgroup_enable_blkio_io = cgroup_enable_blkio_ops = cgroup_enable_blkio_throttle_io = cgroup_enable_blkio_throttle_ops = cgroup_enable_blkio_merged_ops = cgroup_enable_blkio_queued_ops = CONFIG_BOOLEAN_NO; - error("CGROUP: disabled blkio statistics."); + collector_error("CGROUP: disabled blkio statistics."); } } @@ -2568,14 +2568,14 @@ static inline void discovery_find_all_cgroups_v1() { if (discovery_find_dir_in_subdirs(cgroup_memory_base, NULL, discovery_find_cgroup_in_dir_callback) == -1) { cgroup_enable_memory = cgroup_enable_detailed_memory = cgroup_enable_swap = cgroup_enable_memory_failcnt = CONFIG_BOOLEAN_NO; - error("CGROUP: disabled memory statistics."); + collector_error("CGROUP: disabled memory statistics."); } } if (cgroup_search_in_devices) { if (discovery_find_dir_in_subdirs(cgroup_devices_base, NULL, discovery_find_cgroup_in_dir_callback) == -1) { cgroup_search_in_devices = 0; - error("CGROUP: disabled devices statistics."); + collector_error("CGROUP: disabled devices statistics."); } } } @@ -2583,7 +2583,7 @@ static inline void discovery_find_all_cgroups_v1() { static inline void discovery_find_all_cgroups_v2() { if (discovery_find_dir_in_subdirs(cgroup_unified_base, NULL, discovery_find_cgroup_in_dir_callback) == -1) { cgroup_unified_exist = CONFIG_BOOLEAN_NO; - error("CGROUP: disabled unified cgroups statistics."); + collector_error("CGROUP: disabled unified cgroups statistics."); } } @@ -2651,7 +2651,7 @@ static int discovery_is_cgroup_duplicate(struct cgroup *cg) { struct cgroup *c; for (c = discovered_cgroup_root; c; c = c->discovered_next) { if (c != cg && c->enabled && c->hash_chart == cg->hash_chart && !strcmp(c->chart_id, cg->chart_id)) { - error("CGROUP: chart id '%s' already exists with id '%s' and is enabled and available. Disabling cgroup with id '%s'.", cg->chart_id, c->id, cg->id); + collector_error("CGROUP: chart id '%s' already exists with id '%s' and is enabled and available. Disabling cgroup with id '%s'.", cg->chart_id, c->id, cg->id); return 1; } } @@ -2686,7 +2686,7 @@ static inline void discovery_process_cgroup(struct cgroup *cg) { cg->processed = 1; if ((strlen(cg->chart_id) + strlen(cgroup_chart_id_prefix)) >= RRD_ID_LENGTH_MAX) { - info("cgroup '%s' (chart id '%s') disabled because chart_id exceeds the limit (RRD_ID_LENGTH_MAX)", cg->id, cg->chart_id); + collector_info("cgroup '%s' (chart id '%s') disabled because chart_id exceeds the limit (RRD_ID_LENGTH_MAX)", cg->id, cg->chart_id); return; } @@ -2754,10 +2754,20 @@ static inline void discovery_find_all_cgroups() { debug(D_CGROUP, "done searching for cgroups"); } +static void cgroup_discovery_cleanup(void *ptr) { + UNUSED(ptr); + + discovery_thread.exited = 1; + worker_unregister(); + service_exits(); +} + void cgroup_discovery_worker(void *ptr) { UNUSED(ptr); + netdata_thread_cleanup_push(cgroup_discovery_cleanup, ptr); + worker_register("CGROUPSDISC"); worker_register_job_name(WORKER_DISCOVERY_INIT, "init"); worker_register_job_name(WORKER_DISCOVERY_FIND, "find"); @@ -2777,24 +2787,23 @@ void cgroup_discovery_worker(void *ptr) NULL, SIMPLE_PATTERN_EXACT); - while (!netdata_exit) { + while (service_running(SERVICE_COLLECTORS)) { worker_is_idle(); uv_mutex_lock(&discovery_thread.mutex); - while (!discovery_thread.start_discovery) + while (!discovery_thread.start_discovery && service_running(SERVICE_COLLECTORS)) uv_cond_wait(&discovery_thread.cond_var, &discovery_thread.mutex); discovery_thread.start_discovery = 0; uv_mutex_unlock(&discovery_thread.mutex); - if (unlikely(netdata_exit)) + if (unlikely(!service_running(SERVICE_COLLECTORS))) break; discovery_find_all_cgroups(); } - discovery_thread.exited = 1; - worker_unregister(); -} + netdata_thread_cleanup_pop(1); +} // ---------------------------------------------------------------------------- // generate charts @@ -3507,52 +3516,15 @@ static inline char *cgroup_chart_type(char *buffer, const char *id, size_t len) return buffer; } -static inline unsigned long long cpuset_str2ull(char **s) { - unsigned long long n = 0; - char c; - for(c = **s; c >= '0' && c <= '9' ; c = *(++*s)) { - n *= 10; - n += c - '0'; - } - return n; -} - static inline void update_cpu_limits(char **filename, unsigned long long *value, struct cgroup *cg) { if(*filename) { int ret = -1; if(value == &cg->cpuset_cpus) { - static char *buf = NULL; - static size_t buf_size = 0; - - if(!buf) { - buf_size = 100U + 6 * get_system_cpus(); // taken from kernel/cgroup/cpuset.c - buf = mallocz(buf_size + 1); - } - - ret = read_file(*filename, buf, buf_size); - - if(!ret) { - char *s = buf; - unsigned long long ncpus = 0; - - // parse the cpuset string and calculate the number of cpus the cgroup is allowed to use - while(*s) { - unsigned long long n = cpuset_str2ull(&s); - ncpus++; - if(*s == ',') { - s++; - continue; - } - if(*s == '-') { - s++; - unsigned long long m = cpuset_str2ull(&s); - ncpus += m - n; // calculate the number of cpus in the region - } - s++; - } - - if(likely(ncpus)) *value = ncpus; + unsigned long ncpus = read_cpuset_cpus(*filename, get_system_cpus()); + if(ncpus) { + *value = ncpus; + ret = 0; } } else if(value == &cg->cpu_cfs_period) { @@ -3564,7 +3536,7 @@ static inline void update_cpu_limits(char **filename, unsigned long long *value, else ret = -1; if(ret) { - error("Cannot refresh cgroup %s cpu limit by reading '%s'. Will not update its limit anymore.", cg->id, *filename); + collector_error("Cannot refresh cgroup %s cpu limit by reading '%s'. Will not update its limit anymore.", cg->id, *filename); freez(*filename); *filename = NULL; } @@ -3588,7 +3560,7 @@ static inline void update_cpu_limits2(struct cgroup *cg) { unsigned long lines = procfile_lines(ff); if (unlikely(lines < 1)) { - error("CGROUP: file '%s' should have 1 lines.", cg->filename_cpu_cfs_quota); + collector_error("CGROUP: file '%s' should have 1 lines.", cg->filename_cpu_cfs_quota); return; } @@ -3605,7 +3577,7 @@ static inline void update_cpu_limits2(struct cgroup *cg) { return; cpu_limits2_err: - error("Cannot refresh cgroup %s cpu limit by reading '%s'. Will not update its limit anymore.", cg->id, cg->filename_cpu_cfs_quota); + collector_error("Cannot refresh cgroup %s cpu limit by reading '%s'. Will not update its limit anymore.", cg->id, cg->filename_cpu_cfs_quota); freez(cg->filename_cpu_cfs_quota); cg->filename_cpu_cfs_quota = NULL; @@ -3617,7 +3589,7 @@ static inline int update_memory_limits(char **filename, const RRDSETVAR_ACQUIRED if(unlikely(!*chart_var)) { *chart_var = rrdsetvar_custom_chart_variable_add_and_acquire(cg->st_mem_usage, chart_var_name); if(!*chart_var) { - error("Cannot create cgroup %s chart variable '%s'. Will not update its limit anymore.", cg->id, chart_var_name); + collector_error("Cannot create cgroup %s chart variable '%s'. Will not update its limit anymore.", cg->id, chart_var_name); freez(*filename); *filename = NULL; } @@ -3626,7 +3598,7 @@ static inline int update_memory_limits(char **filename, const RRDSETVAR_ACQUIRED if(*filename && *chart_var) { if(!(cg->options & CGROUP_OPTIONS_IS_UNIFIED)) { if(read_single_number_file(*filename, value)) { - error("Cannot refresh cgroup %s memory limit by reading '%s'. Will not update its limit anymore.", cg->id, *filename); + collector_error("Cannot refresh cgroup %s memory limit by reading '%s'. Will not update its limit anymore.", cg->id, *filename); freez(*filename); *filename = NULL; } @@ -3638,7 +3610,7 @@ static inline int update_memory_limits(char **filename, const RRDSETVAR_ACQUIRED char buffer[30 + 1]; int ret = read_file(*filename, buffer, 30); if(ret) { - error("Cannot refresh cgroup %s memory limit by reading '%s'. Will not update its limit anymore.", cg->id, *filename); + collector_error("Cannot refresh cgroup %s memory limit by reading '%s'. Will not update its limit anymore.", cg->id, *filename); freez(*filename); *filename = NULL; return 0; @@ -3747,7 +3719,7 @@ void update_cgroup_charts(int update_every) { if(unlikely(!cg->chart_var_cpu_limit)) { cg->chart_var_cpu_limit = rrdsetvar_custom_chart_variable_add_and_acquire(cg->st_cpu, "cpu_limit"); if(!cg->chart_var_cpu_limit) { - error("Cannot create cgroup %s chart variable 'cpu_limit'. Will not update its limit anymore.", cg->id); + collector_error("Cannot create cgroup %s chart variable 'cpu_limit'. Will not update its limit anymore.", cg->id); if(cg->filename_cpuset_cpus) freez(cg->filename_cpuset_cpus); cg->filename_cpuset_cpus = NULL; if(cg->filename_cpu_cfs_period) freez(cg->filename_cpu_cfs_period); @@ -4139,7 +4111,7 @@ void update_cgroup_charts(int update_every) { if(likely(ff && procfile_lines(ff) && !strncmp(procfile_word(ff, 0), "MemTotal", 8))) ram_total = str2ull(procfile_word(ff, 1)) * 1024; else { - error("Cannot read file %s. Will not update cgroup %s RAM limit anymore.", filename, cg->id); + collector_error("Cannot read file %s. Will not update cgroup %s RAM limit anymore.", filename, cg->id); freez(cg->filename_memory_limit); cg->filename_memory_limit = NULL; } @@ -4773,19 +4745,19 @@ static void cgroup_main_cleanup(void *ptr) { struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; static_thread->enabled = NETDATA_MAIN_THREAD_EXITING; - info("cleaning up..."); + collector_info("cleaning up..."); usec_t max = 2 * USEC_PER_SEC, step = 50000; if (!discovery_thread.exited) { - info("stopping discovery thread worker"); + collector_info("stopping discovery thread worker"); uv_mutex_lock(&discovery_thread.mutex); discovery_thread.start_discovery = 1; uv_cond_signal(&discovery_thread.cond_var); uv_mutex_unlock(&discovery_thread.mutex); } - info("waiting for discovery thread to finish..."); + collector_info("waiting for discovery thread to finish..."); while (!discovery_thread.exited && max > 0) { max -= step; @@ -4824,7 +4796,7 @@ void *cgroups_main(void *ptr) { netdata_cgroup_ebpf_initialize_shm(); if (uv_mutex_init(&cgroup_root_mutex)) { - error("CGROUP: cannot initialize mutex for the main cgroup list"); + collector_error("CGROUP: cannot initialize mutex for the main cgroup list"); goto exit; } @@ -4833,17 +4805,17 @@ void *cgroups_main(void *ptr) { discovery_thread.exited = 0; if (uv_mutex_init(&discovery_thread.mutex)) { - error("CGROUP: cannot initialize mutex for discovery thread"); + collector_error("CGROUP: cannot initialize mutex for discovery thread"); goto exit; } if (uv_cond_init(&discovery_thread.cond_var)) { - error("CGROUP: cannot initialize conditional variable for discovery thread"); + collector_error("CGROUP: cannot initialize conditional variable for discovery thread"); goto exit; } int error = uv_thread_create(&discovery_thread.thread, cgroup_discovery_worker, NULL); if (error) { - error("CGROUP: cannot create thread worker. uv_thread_create(): %s", uv_strerror(error)); + collector_error("CGROUP: cannot create thread worker. uv_thread_create(): %s", uv_strerror(error)); goto exit; } uv_thread_set_name_np(discovery_thread.thread, "PLUGIN[cgroups]"); @@ -4853,11 +4825,11 @@ void *cgroups_main(void *ptr) { usec_t step = cgroup_update_every * USEC_PER_SEC; usec_t find_every = cgroup_check_for_new_every * USEC_PER_SEC, find_dt = 0; - while(!netdata_exit) { + while(service_running(SERVICE_COLLECTORS)) { worker_is_idle(); usec_t hb_dt = heartbeat_next(&hb, step); - if(unlikely(netdata_exit)) break; + if(unlikely(!service_running(SERVICE_COLLECTORS))) break; find_dt += hb_dt; if (unlikely(find_dt >= find_every || (!is_inside_k8s && cgroups_check))) { @@ -4872,9 +4844,11 @@ void *cgroups_main(void *ptr) { worker_is_busy(WORKER_CGROUPS_READ); read_all_discovered_cgroups(cgroup_root); + if(unlikely(!service_running(SERVICE_COLLECTORS))) break; worker_is_busy(WORKER_CGROUPS_CHART); update_cgroup_charts(cgroup_update_every); + if(unlikely(!service_running(SERVICE_COLLECTORS))) break; worker_is_idle(); uv_mutex_unlock(&cgroup_root_mutex); |