apps.plugin logs repeating errors, only once per process; fixes #779
Costa Tsaousis committed
Aug 14, 2016 at 15:33 UTC
a9e6334edcec1af647e84bd85542fd467d8e9a33
1 file changed
+78
-51
src/apps_plugin.c
+78
-51
@@ -394,11 +394,19 @@ int read_apps_groups_conf(const char *name)
394
// data to store for each pid
395
// see: man proc
396
397
+#define PID_LOG_IO 0x00000001
398
+#define PID_LOG_STATM 0x00000002
399
+#define PID_LOG_CMDLINE 0x00000004
400
+#define PID_LOG_FDS 0x00000008
401
+#define PID_LOG_STAT 0x00000010
402
+
403
struct pid_stat {
404
int32_t pid;
405
char comm[MAX_COMPARE_NAME + 1];
406
char cmdline[MAX_CMDLINE + 1];
407
408
+ uint32_t log_thrown;
409
+
410
// char state;
411
int32_t ppid;
412
// int32_t pgrp;
@@ -583,7 +591,7 @@ int read_proc_pid_cmdline(struct pid_stat *p) {
591
ssize_t i, bytes = read(fd, p->cmdline, MAX_CMDLINE);
592
close(fd);
593
586
- if(unlikely(bytes <= 0)) goto cleanup;
594
+ if(unlikely(bytes < 0)) goto cleanup;
595
596
p->cmdline[bytes] = '\0';
597
for(i = 0; i < bytes ; i++)
@@ -592,7 +600,7 @@ int read_proc_pid_cmdline(struct pid_stat *p) {
600
if(unlikely(debug))
601
fprintf(stderr, "Read file '%s' contents: %s\n", p->cmdline_filename, p->cmdline);
602
595
- return 0;
603
+ return 1;
604
605
cleanup:
606
// copy the command to the command line
@@ -603,7 +611,7 @@ cleanup:
611
int read_proc_pid_ownership(struct pid_stat *p) {
612
if(unlikely(!p->stat_filename)) {
613
error("pid %d does not have a stat_filename", p->pid);
606
- return 1;
614
+ return 0;
615
}
616
617
// ----------------------------------------
@@ -618,7 +626,7 @@ int read_proc_pid_ownership(struct pid_stat *p) {
626
p->uid = st.st_uid;
627
p->gid = st.st_gid;
628
621
- return 0;
629
+ return 1;
630
}
631
632
int read_proc_pid_stat(struct pid_stat *p) {
@@ -749,7 +757,7 @@ int read_proc_pid_stat(struct pid_stat *p) {
757
p->cgtime = 0;
758
}
759
752
- return 0;
760
+ return 1;
761
762
cleanup:
763
p->minflt = 0;
@@ -764,7 +772,7 @@ cleanup:
772
p->cgtime = 0;
773
p->num_threads = 0;
774
p->rss = 0;
767
- return 1;
775
+ return 0;
776
}
777
778
int read_proc_pid_statm(struct pid_stat *p) {
@@ -792,7 +800,7 @@ int read_proc_pid_statm(struct pid_stat *p) {
800
p->statm_data = strtoull(procfile_lineword(ff, 0, 5), NULL, 10);
801
p->statm_dirty = strtoull(procfile_lineword(ff, 0, 6), NULL, 10);
802
795
- return 0;
803
+ return 1;
804
805
cleanup:
806
p->statm_size = 0;
@@ -802,7 +810,7 @@ cleanup:
810
p->statm_lib = 0;
811
p->statm_data = 0;
812
p->statm_dirty = 0;
805
- return 1;
813
+ return 0;
814
}
815
816
int read_proc_pid_io(struct pid_stat *p) {
@@ -866,7 +874,7 @@ int read_proc_pid_io(struct pid_stat *p) {
874
p->io_cancelled_write_bytes = 0;
875
}
876
869
- return 0;
877
+ return 1;
878
879
cleanup:
880
p->io_logical_bytes_read = 0;
@@ -876,7 +884,7 @@ cleanup:
884
p->io_storage_bytes_read = 0;
885
p->io_storage_bytes_written = 0;
886
p->io_cancelled_write_bytes = 0;
879
- return 1;
887
+ return 0;
888
}
889
890
unsigned long long global_utime = 0;
@@ -937,13 +945,13 @@ int read_proc_stat() {
945
global_gtime = 0;
946
}
947
940
- return 0;
948
+ return 1;
949
950
cleanup:
951
global_utime = 0;
952
global_stime = 0;
953
global_gtime = 0;
946
- return 1;
954
+ return 0;
955
}
956
957
@@ -1248,7 +1256,7 @@ int read_pid_file_descriptors(struct pid_stat *p) {
1256
1257
// else make it positive again, we need it
1258
// of course, the actual file may have changed, but we don't care so much
1251
- // FIXME: we could compare the inode as returned by readdir direct structure
1259
+ // FIXME: we could compare the inode as returned by readdir dirent structure
1260
else p->fds[fdid] = -p->fds[fdid];
1261
}
1262
closedir(fds);
@@ -1259,9 +1267,9 @@ int read_pid_file_descriptors(struct pid_stat *p) {
1267
p->fds[c] = 0;
1268
}
1269
}
1262
- else return 1;
1270
+ else return 0;
1271
1264
- return 0;
1272
+ return 1;
1273
}
1274
1275
// ----------------------------------------------------------------------------
@@ -1571,6 +1579,49 @@ static int compar_pid(const void *pid1, const void *pid2) {
1579
return 1;
1580
}
1581
1582
+static inline int managed_log(struct pid_stat *p, uint32_t log, int status) {
1583
+ if(unlikely(!status)) {
1584
+ // error("command failed log %u, errno %d", log, errno);
1585
+
1586
+ if(unlikely(debug || errno != ENOENT)) {
1587
+ if(unlikely(debug || !(p->log_thrown & log))) {
1588
+ p->log_thrown |= log;
1589
+ switch(log) {
1590
+ case PID_LOG_IO:
1591
+ error("Cannot process %s/proc/%d/io (command '%s')", host_prefix, p->pid, p->comm);
1592
+ break;
1593
+
1594
+ case PID_LOG_STATM:
1595
+ error("Cannot process %s/proc/%d/statm (command '%s')", host_prefix, p->pid, p->comm);
1596
+ break;
1597
+
1598
+ case PID_LOG_CMDLINE:
1599
+ error("Cannot process %s/proc/%d/cmdline (command '%s')", host_prefix, p->pid, p->comm);
1600
+ break;
1601
+
1602
+ case PID_LOG_FDS:
1603
+ error("Cannot process entries in %s/proc/%d/fd (command '%s')", host_prefix, p->pid, p->comm);
1604
+ break;
1605
+
1606
+ case PID_LOG_STAT:
1607
+ break;
1608
+
1609
+ default:
1610
+ error("unhandled error for pid %d, command '%s'", p->pid, p->comm);
1611
+ break;
1612
+ }
1613
+ }
1614
+ }
1615
+ errno = 0;
1616
+ }
1617
+ else if(unlikely(p->log_thrown & log)) {
1618
+ // error("unsetting log %u on pid %d", log, p->pid);
1619
+ p->log_thrown &= ~log;
1620
+ }
1621
+
1622
+ return status;
1623
+}
1624
+
1625
void collect_data_for_pid(pid_t pid) {
1626
if(unlikely(pid <= 0 || pid > pid_max)) {
1627
error("Invalid pid %d read (expected 1 to %d). Ignoring process.", pid, pid_max);
@@ -1586,14 +1637,9 @@ void collect_data_for_pid(pid_t pid) {
1637
// --------------------------------------------------------------------
1638
// /proc/<pid>/stat
1639
1589
- if(unlikely(read_proc_pid_stat(p))) {
1590
- if(errno != ENOENT || debug)
1591
- error("Cannot process %s/proc/%d/stat (command '%s')", host_prefix, pid, p->comm);
1592
- else
1593
- errno = 0;
1640
+ if(unlikely(!managed_log(p, PID_LOG_STAT, read_proc_pid_stat(p))))
1641
// there is no reason to proceed if we cannot get its status
1642
return;
1596
- }
1643
1644
read_proc_pid_ownership(p);
1645
@@ -1606,24 +1652,14 @@ void collect_data_for_pid(pid_t pid) {
1652
// --------------------------------------------------------------------
1653
// /proc/<pid>/io
1654
1609
- if(unlikely(read_proc_pid_io(p))) {
1610
- if(errno != ENOENT || debug)
1611
- error("Cannot process %s/proc/%d/io (command '%s')", host_prefix, pid, p->comm);
1612
- else
1613
- errno = 0;
1614
- }
1655
+ managed_log(p, PID_LOG_IO, read_proc_pid_io(p));
1656
1657
// --------------------------------------------------------------------
1658
// /proc/<pid>/statm
1659
1619
- if(unlikely(read_proc_pid_statm(p))) {
1620
- if(errno != ENOENT || debug)
1621
- error("Cannot process %s/proc/%d/statm (command '%s')", host_prefix, pid, p->comm);
1622
- else
1623
- errno = 0;
1660
+ if(unlikely(!managed_log(p, PID_LOG_STATM, read_proc_pid_statm(p))))
1661
// there is no reason to proceed if we cannot get its memory status
1662
return;
1626
- }
1663
1664
// --------------------------------------------------------------------
1665
// link it
@@ -1632,14 +1668,8 @@ void collect_data_for_pid(pid_t pid) {
1668
// we do this only once, the first time this pid is loaded
1669
if(unlikely(p->new_entry)) {
1670
// /proc/<pid>/cmdline
1635
- if(likely(proc_pid_cmdline_is_needed)) {
1636
- if(unlikely(read_proc_pid_cmdline(p))) {
1637
- if(errno != ENOENT || debug)
1638
- error("Cannot process %s/proc/%d/cmdline (command '%s')", host_prefix, pid, p->comm);
1639
- else
1640
- errno = 0;
1641
- }
1642
- }
1671
+ if(likely(proc_pid_cmdline_is_needed))
1672
+ managed_log(p, PID_LOG_CMDLINE, read_proc_pid_cmdline(p));
1673
1674
if(unlikely(debug))
1675
fprintf(stderr, "apps.plugin: \tJust added %d (%s)\n", pid, p->comm);
@@ -1675,12 +1705,7 @@ void collect_data_for_pid(pid_t pid) {
1705
// --------------------------------------------------------------------
1706
// /proc/<pid>/fd
1707
1678
- if(unlikely(read_pid_file_descriptors(p))) {
1679
- if(errno != ENOENT || debug)
1680
- error("Cannot process entries in %s/proc/%d/fd (command '%s')", host_prefix, pid, p->comm);
1681
- else
1682
- errno = 0;
1683
- }
1708
+ managed_log(p, PID_LOG_FDS, read_pid_file_descriptors(p));
1709
1710
// --------------------------------------------------------------------
1711
// done!
@@ -2752,6 +2777,8 @@ int main(int argc, char **argv)
2777
// set the name for logging
2778
program_name = "apps.plugin";
2779
2780
+ info("started on pid %d", getpid());
2781
+
2782
// disable syslog for apps.plugin
2783
error_log_syslog = 0;
2784
@@ -2761,17 +2788,17 @@ int main(int argc, char **argv)
2788
2789
host_prefix = getenv("NETDATA_HOST_PREFIX");
2790
if(host_prefix == NULL) {
2764
- info("NETDATA_HOST_PREFIX is not passed from netdata");
2791
+ // info("NETDATA_HOST_PREFIX is not passed from netdata");
2792
host_prefix = "";
2793
}
2767
- else info("Found NETDATA_HOST_PREFIX='%s'", host_prefix);
2794
+ // else info("Found NETDATA_HOST_PREFIX='%s'", host_prefix);
2795
2796
config_dir = getenv("NETDATA_CONFIG_DIR");
2797
if(config_dir == NULL) {
2771
- info("NETDATA_CONFIG_DIR is not passed from netdata");
2798
+ // info("NETDATA_CONFIG_DIR is not passed from netdata");
2799
config_dir = CONFIG_DIR;
2800
}
2774
- else info("Found NETDATA_CONFIG_DIR='%s'", config_dir);
2801
+ // else info("Found NETDATA_CONFIG_DIR='%s'", config_dir);
2802
2803
#ifdef NETDATA_INTERNAL_CHECKS
2804
if(debug_flags != 0) {