10
#include "libnetdata/libnetdata.h"
11
#include "libnetdata/required_dummies.h"
12
13
+#define APPS_PLUGIN_FUNCTIONS() do { \
14
+ fprintf(stdout, PLUGINSD_KEYWORD_FUNCTION " \"processes\" 10 \"Detailed information on the currently running processes on this node\"\n"); \
15
+ } while(0)
16
+
17
+
18
// ----------------------------------------------------------------------------
19
// debugging
20
196
struct pid_on_target *next;
197
};
198
199
+struct openfds {
200
+ kernel_uint_t files;
201
+ kernel_uint_t pipes;
202
+ kernel_uint_t sockets;
203
+ kernel_uint_t inotifies;
204
+ kernel_uint_t eventfds;
205
+ kernel_uint_t timerfds;
206
+ kernel_uint_t signalfds;
207
+ kernel_uint_t eventpolls;
208
+ kernel_uint_t other;
209
+};
210
+
211
// ----------------------------------------------------------------------------
212
// target
213
//
252
253
kernel_uint_t io_logical_bytes_read;
254
kernel_uint_t io_logical_bytes_written;
238
- // kernel_uint_t io_read_calls;
239
- // kernel_uint_t io_write_calls;
255
+ kernel_uint_t io_read_calls;
256
+ kernel_uint_t io_write_calls;
257
kernel_uint_t io_storage_bytes_read;
258
kernel_uint_t io_storage_bytes_written;
242
- // kernel_uint_t io_cancelled_write_bytes;
259
+ kernel_uint_t io_cancelled_write_bytes;
260
261
int *target_fds;
262
int target_fds_size;
263
247
- kernel_uint_t openfiles;
248
- kernel_uint_t openpipes;
249
- kernel_uint_t opensockets;
250
- kernel_uint_t openinotifies;
251
- kernel_uint_t openeventfds;
252
- kernel_uint_t opentimerfds;
253
- kernel_uint_t opensignalfds;
254
- kernel_uint_t openeventpolls;
255
- kernel_uint_t openother;
264
+ struct openfds openfds;
265
266
kernel_uint_t starttime;
267
kernel_uint_t collected_starttime;
391
392
kernel_uint_t io_logical_bytes_read_raw;
393
kernel_uint_t io_logical_bytes_written_raw;
385
- // kernel_uint_t io_read_calls_raw;
386
- // kernel_uint_t io_write_calls_raw;
394
+ kernel_uint_t io_read_calls_raw;
395
+ kernel_uint_t io_write_calls_raw;
396
kernel_uint_t io_storage_bytes_read_raw;
397
kernel_uint_t io_storage_bytes_written_raw;
389
- // kernel_uint_t io_cancelled_write_bytes_raw;
398
+ kernel_uint_t io_cancelled_write_bytes_raw;
399
400
kernel_uint_t io_logical_bytes_read;
401
kernel_uint_t io_logical_bytes_written;
393
- // kernel_uint_t io_read_calls;
394
- // kernel_uint_t io_write_calls;
402
+ kernel_uint_t io_read_calls;
403
+ kernel_uint_t io_write_calls;
404
kernel_uint_t io_storage_bytes_read;
405
kernel_uint_t io_storage_bytes_written;
397
- // kernel_uint_t io_cancelled_write_bytes;
406
+ kernel_uint_t io_cancelled_write_bytes;
407
408
struct pid_fd *fds; // array of fds it uses
400
- size_t fds_size; // the size of the fds array
409
+ size_t fds_size; // the size of the fds array
410
+
411
+ struct openfds openfds;
412
413
int children_count; // number of processes directly referencing this
414
unsigned char keep:1; // 1 when we need to keep this process in memory even after it exited
458
459
static struct pid_stat
460
*root_of_pids = NULL, // global list of all processes running
450
- **all_pids = NULL; // to avoid allocations, we pre-allocate the
451
- // the entire pid space.
461
+ **all_pids = NULL; // to avoid allocations, we pre-allocate
462
+ // a pointer for each pid in the entire pid space.
463
464
static size_t
465
all_pids_count = 0; // the number of processes running
972
p->fds = mallocz(sizeof(struct pid_fd) * MAX_SPARE_FDS);
973
p->fds_size = MAX_SPARE_FDS;
974
init_pid_fds(p, 0, p->fds_size);
964
-
965
- if(likely(root_of_pids))
966
- root_of_pids->prev = p;
967
-
968
- p->next = root_of_pids;
969
- root_of_pids = p;
970
-
975
p->pid = pid;
976
977
+ DOUBLE_LINKED_LIST_APPEND_UNSAFE(root_of_pids, p, prev, next);
978
+
979
all_pids[pid] = p;
980
all_pids_count++;
981
992
993
debug_log("process %d %s exited, deleting it.", pid, p->comm);
994
989
- if(root_of_pids == p)
990
- root_of_pids = p->next;
991
-
992
- if(p->next) p->next->prev = p->prev;
993
- if(p->prev) p->prev->next = p->next;
995
+ DOUBLE_LINKED_LIST_REMOVE_UNSAFE(root_of_pids, p, prev, next);
996
997
// free the filename
998
#ifndef __FreeBSD__
1556
#else
1557
pid_incremental_rate(io, p->io_logical_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 0, 1)));
1558
pid_incremental_rate(io, p->io_logical_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 1, 1)));
1557
- // pid_incremental_rate(io, p->io_read_calls, str2kernel_uint_t(procfile_lineword(ff, 2, 1)));
1558
- // pid_incremental_rate(io, p->io_write_calls, str2kernel_uint_t(procfile_lineword(ff, 3, 1)));
1559
+ pid_incremental_rate(io, p->io_read_calls, str2kernel_uint_t(procfile_lineword(ff, 2, 1)));
1560
+ pid_incremental_rate(io, p->io_write_calls, str2kernel_uint_t(procfile_lineword(ff, 3, 1)));
1561
pid_incremental_rate(io, p->io_storage_bytes_read, str2kernel_uint_t(procfile_lineword(ff, 4, 1)));
1562
pid_incremental_rate(io, p->io_storage_bytes_written, str2kernel_uint_t(procfile_lineword(ff, 5, 1)));
1561
- // pid_incremental_rate(io, p->io_cancelled_write_bytes, str2kernel_uint_t(procfile_lineword(ff, 6, 1)));
1563
+ pid_incremental_rate(io, p->io_cancelled_write_bytes, str2kernel_uint_t(procfile_lineword(ff, 6, 1)));
1564
#endif
1565
1566
if(unlikely(global_iterations_counter == 1)) {
1567
p->io_logical_bytes_read = 0;
1568
p->io_logical_bytes_written = 0;
1567
- // p->io_read_calls = 0;
1568
- // p->io_write_calls = 0;
1569
+ p->io_read_calls = 0;
1570
+ p->io_write_calls = 0;
1571
p->io_storage_bytes_read = 0;
1572
p->io_storage_bytes_written = 0;
1571
- // p->io_cancelled_write_bytes = 0;
1573
+ p->io_cancelled_write_bytes = 0;
1574
}
1575
1576
return 1;
1579
cleanup:
1580
p->io_logical_bytes_read = 0;
1581
p->io_logical_bytes_written = 0;
1580
- // p->io_read_calls = 0;
1581
- // p->io_write_calls = 0;
1582
+ p->io_read_calls = 0;
1583
+ p->io_write_calls = 0;
1584
p->io_storage_bytes_read = 0;
1585
p->io_storage_bytes_written = 0;
1584
- // p->io_cancelled_write_bytes = 0;
1586
+ p->io_cancelled_write_bytes = 0;
1587
return 0;
1588
#endif
1589
}
1890
else if(likely(strncmp(name, "anon_inode:", 11) == 0)) {
1891
const char *t = &name[11];
1892
1891
- if(strcmp(t, "inotify") == 0) type = FILETYPE_INOTIFY;
1893
+ if(strcmp(t, "inotify") == 0) type = FILETYPE_INOTIFY;
1894
else if(strcmp(t, "[eventfd]") == 0) type = FILETYPE_EVENTFD;
1895
else if(strcmp(t, "[eventpoll]") == 0) type = FILETYPE_EVENTPOLL;
1896
else if(strcmp(t, "[timerfd]") == 0) type = FILETYPE_TIMERFD;
1945
1946
static inline void init_pid_fds(struct pid_stat *p, size_t first, size_t size) {
1947
struct pid_fd *pfd = &p->fds[first], *pfdend = &p->fds[first + size];
1946
- size_t i = first;
1948
1949
while(pfd < pfdend) {
1950
#ifndef __FreeBSD__
1952
#endif
1953
clear_pid_fd(pfd);
1954
pfd++;
1954
- i++;
1955
}
1956
}
1957
2904
2905
w->io_logical_bytes_read = 0;
2906
w->io_logical_bytes_written = 0;
2907
- // w->io_read_calls = 0;
2908
- // w->io_write_calls = 0;
2907
+ w->io_read_calls = 0;
2908
+ w->io_write_calls = 0;
2909
w->io_storage_bytes_read = 0;
2910
w->io_storage_bytes_written = 0;
2911
- // w->io_cancelled_write_bytes = 0;
2911
+ w->io_cancelled_write_bytes = 0;
2912
2913
// zero file counters
2914
if(w->target_fds) {
2915
memset(w->target_fds, 0, sizeof(int) * w->target_fds_size);
2916
- w->openfiles = 0;
2917
- w->openpipes = 0;
2918
- w->opensockets = 0;
2919
- w->openinotifies = 0;
2920
- w->openeventfds = 0;
2921
- w->opentimerfds = 0;
2922
- w->opensignalfds = 0;
2923
- w->openeventpolls = 0;
2924
- w->openother = 0;
2916
+ w->openfds.files = 0;
2917
+ w->openfds.pipes = 0;
2918
+ w->openfds.sockets = 0;
2919
+ w->openfds.inotifies = 0;
2920
+ w->openfds.eventfds = 0;
2921
+ w->openfds.timerfds = 0;
2922
+ w->openfds.signalfds = 0;
2923
+ w->openfds.eventpolls = 0;
2924
+ w->openfds.other = 0;
2925
}
2926
2927
w->collected_starttime = 0;
2956
}
2957
}
2958
2959
-static inline void aggregate_fd_on_target(int fd, struct target *w) {
2960
- if(unlikely(!w))
2961
- return;
2962
-
2963
- if(unlikely(w->target_fds[fd])) {
2964
- // it is already aggregated
2965
- // just increase its usage counter
2966
- w->target_fds[fd]++;
2967
- return;
2968
- }
2969
-
2970
- // increase its usage counter
2971
- // so that we will not add it again
2972
- w->target_fds[fd]++;
2973
-
2974
- switch(all_files[fd].type) {
2959
+static void aggregage_fd_type_on_openfds(FD_FILETYPE type, struct openfds *openfds) {
2960
+ switch(type) {
2961
case FILETYPE_FILE:
2976
- w->openfiles++;
2962
+ openfds->files++;
2963
break;
2964
2965
case FILETYPE_PIPE:
2980
- w->openpipes++;
2966
+ openfds->pipes++;
2967
break;
2968
2969
case FILETYPE_SOCKET:
2984
- w->opensockets++;
2970
+ openfds->sockets++;
2971
break;
2972
2973
case FILETYPE_INOTIFY:
2988
- w->openinotifies++;
2974
+ openfds->inotifies++;
2975
break;
2976
2977
case FILETYPE_EVENTFD:
2992
- w->openeventfds++;
2978
+ openfds->eventfds++;
2979
break;
2980
2981
case FILETYPE_TIMERFD:
2996
- w->opentimerfds++;
2982
+ openfds->timerfds++;
2983
break;
2984
2985
case FILETYPE_SIGNALFD:
3000
- w->opensignalfds++;
2986
+ openfds->signalfds++;
2987
break;
2988
2989
case FILETYPE_EVENTPOLL:
3004
- w->openeventpolls++;
2990
+ openfds->eventpolls++;
2991
break;
2992
2993
case FILETYPE_OTHER:
3008
- w->openother++;
2994
+ openfds->other++;
2995
break;
2996
}
2997
}
2998
2999
+static inline void aggregate_fd_on_target(int fd, struct target *w) {
3000
+ if(unlikely(!w))
3001
+ return;
3002
+
3003
+ if(unlikely(w->target_fds[fd])) {
3004
+ // it is already aggregated
3005
+ // just increase its usage counter
3006
+ w->target_fds[fd]++;
3007
+ return;
3008
+ }
3009
+
3010
+ // increase its usage counter
3011
+ // so that we will not add it again
3012
+ w->target_fds[fd]++;
3013
+
3014
+ aggregage_fd_type_on_openfds(all_files[fd].type, &w->openfds);
3015
+}
3016
+
3017
static inline void aggregate_pid_fds_on_targets(struct pid_stat *p) {
3018
3019
if(unlikely(!p->updated)) {
3027
reallocate_target_fds(u);
3028
reallocate_target_fds(g);
3029
3030
+ p->openfds.files = 0;
3031
+ p->openfds.pipes = 0;
3032
+ p->openfds.sockets = 0;
3033
+ p->openfds.inotifies = 0;
3034
+ p->openfds.eventfds = 0;
3035
+ p->openfds.timerfds = 0;
3036
+ p->openfds.signalfds = 0;
3037
+ p->openfds.eventpolls = 0;
3038
+ p->openfds.other = 0;
3039
+
3040
long currentfds = 0;
3041
size_t c, size = p->fds_size;
3042
struct pid_fd *fds = p->fds;
3047
continue;
3048
3049
currentfds++;
3050
+ aggregage_fd_type_on_openfds(all_files[fd].type, &p->openfds);
3051
3052
aggregate_fd_on_target(fd, w);
3053
aggregate_fd_on_target(fd, u);
3094
3095
w->io_logical_bytes_read += p->io_logical_bytes_read;
3096
w->io_logical_bytes_written += p->io_logical_bytes_written;
3082
- // w->io_read_calls += p->io_read_calls;
3083
- // w->io_write_calls += p->io_write_calls;
3097
+ w->io_read_calls += p->io_read_calls;
3098
+ w->io_write_calls += p->io_write_calls;
3099
w->io_storage_bytes_read += p->io_storage_bytes_read;
3100
w->io_storage_bytes_written += p->io_storage_bytes_written;
3086
- // w->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
3101
+ w->io_cancelled_write_bytes += p->io_cancelled_write_bytes;
3102
3103
w->processes++;
3104
w->num_threads += p->num_threads;
3653
send_BEGIN(type, "files", dt);
3654
for (w = root; w; w = w->next) {
3655
if (unlikely(w->exposed && w->processes))
3641
- send_SET(w->name, w->openfiles);
3656
+ send_SET(w->name, w->openfds.files);
3657
}
3658
if (!strcmp("apps", type)){
3659
kernel_uint_t usedfdpercentage = (kernel_uint_t) ((currentmaxfds * 100) / sysconf(_SC_OPEN_MAX));
3664
send_BEGIN(type, "sockets", dt);
3665
for (w = root; w; w = w->next) {
3666
if (unlikely(w->exposed && w->processes))
3652
- send_SET(w->name, w->opensockets);
3667
+ send_SET(w->name, w->openfds.sockets);
3668
}
3669
send_END();
3670
3671
send_BEGIN(type, "pipes", dt);
3672
for (w = root; w; w = w->next) {
3673
if (unlikely(w->exposed && w->processes))
3659
- send_SET(w->name, w->openpipes);
3674
+ send_SET(w->name, w->openfds.pipes);
3675
}
3676
send_END();
3677
}
3719
if(unlikely(w->exposed))
3720
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu %s\n", w->name, time_factor * RATES_DETAIL / 100, w->hidden ? "hidden" : "");
3721
}
3722
+ APPS_PLUGIN_FUNCTIONS();
3723
3724
fprintf(stdout, "CHART %s.mem '' '%s Real Memory (w/o shared)' 'MiB' mem %s.mem stacked 20003 %d\n", type, title, type, update_every);
3725
for (w = root; w ; w = w->next) {
3726
if(unlikely(w->exposed))
3727
fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L);
3728
}
3729
+ APPS_PLUGIN_FUNCTIONS();
3730
+
3731
3732
fprintf(stdout, "CHART %s.vmem '' '%s Virtual Memory Size' 'MiB' mem %s.vmem stacked 20005 %d\n", type, title, type, update_every);
3733
for (w = root; w ; w = w->next) {
3734
if(unlikely(w->exposed))
3735
fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L);
3736
}
3737
+ APPS_PLUGIN_FUNCTIONS();
3738
3739
fprintf(stdout, "CHART %s.threads '' '%s Threads' 'threads' processes %s.threads stacked 20006 %d\n", type, title, type, update_every);
3740
for (w = root; w ; w = w->next) {
3741
if(unlikely(w->exposed))
3742
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3743
}
3744
+ APPS_PLUGIN_FUNCTIONS();
3745
3746
fprintf(stdout, "CHART %s.processes '' '%s Processes' 'processes' processes %s.processes stacked 20007 %d\n", type, title, type, update_every);
3747
for (w = root; w ; w = w->next) {
3748
if(unlikely(w->exposed))
3749
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3750
}
3751
+ APPS_PLUGIN_FUNCTIONS();
3752
3753
#ifndef __FreeBSD__
3754
fprintf(stdout, "CHART %s.uptime '' '%s Carried Over Uptime' 'seconds' processes %s.uptime line 20008 %d\n", type, title, type, update_every);
3756
if(unlikely(w->exposed))
3757
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3758
}
3759
+ APPS_PLUGIN_FUNCTIONS();
3760
3761
if (enable_detailed_uptime_charts) {
3762
fprintf(stdout, "CHART %s.uptime_min '' '%s Minimum Uptime' 'seconds' processes %s.uptime_min line 20009 %d\n", type, title, type, update_every);
3764
if(unlikely(w->exposed))
3765
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3766
}
3767
+ APPS_PLUGIN_FUNCTIONS();
3768
3769
fprintf(stdout, "CHART %s.uptime_avg '' '%s Average Uptime' 'seconds' processes %s.uptime_avg line 20010 %d\n", type, title, type, update_every);
3770
for (w = root; w ; w = w->next) {
3771
if(unlikely(w->exposed))
3772
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3773
}
3774
+ APPS_PLUGIN_FUNCTIONS();
3775
3776
fprintf(stdout, "CHART %s.uptime_max '' '%s Maximum Uptime' 'seconds' processes %s.uptime_max line 20011 %d\n", type, title, type, update_every);
3777
for (w = root; w ; w = w->next) {
3778
if(unlikely(w->exposed))
3779
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3780
}
3781
+ APPS_PLUGIN_FUNCTIONS();
3782
}
3783
#endif
3784
3787
if(unlikely(w->exposed))
3788
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, time_factor * RATES_DETAIL / 100LLU);
3789
}
3790
+ APPS_PLUGIN_FUNCTIONS();
3791
3792
fprintf(stdout, "CHART %s.cpu_system '' '%s CPU System Time (100%% = 1 core)' 'percentage' cpu %s.cpu_system stacked 20021 %d\n", type, title, type, update_every);
3793
for (w = root; w ; w = w->next) {
3794
if(unlikely(w->exposed))
3795
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, time_factor * RATES_DETAIL / 100LLU);
3796
}
3797
+ APPS_PLUGIN_FUNCTIONS();
3798
3799
if(show_guest_time) {
3800
fprintf(stdout, "CHART %s.cpu_guest '' '%s CPU Guest Time (100%% = 1 core)' 'percentage' cpu %s.cpu_guest stacked 20022 %d\n", type, title, type, update_every);
3802
if(unlikely(w->exposed))
3803
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, time_factor * RATES_DETAIL / 100LLU);
3804
}
3805
+ APPS_PLUGIN_FUNCTIONS();
3806
}
3807
3808
#ifndef __FreeBSD__
3811
if(unlikely(w->exposed))
3812
fprintf(stdout, "DIMENSION %s '' absolute %ld %ld\n", w->name, 1L, 1024L);
3813
}
3814
+ APPS_PLUGIN_FUNCTIONS();
3815
#endif
3816
3817
fprintf(stdout, "CHART %s.major_faults '' '%s Major Page Faults (swap read)' 'page faults/s' swap %s.major_faults stacked 20012 %d\n", type, title, type, update_every);
3819
if(unlikely(w->exposed))
3820
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
3821
}
3822
+ APPS_PLUGIN_FUNCTIONS();
3823
3824
fprintf(stdout, "CHART %s.minor_faults '' '%s Minor Page Faults' 'page faults/s' mem %s.minor_faults stacked 20011 %d\n", type, title, type, update_every);
3825
for (w = root; w ; w = w->next) {
3826
if(unlikely(w->exposed))
3827
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
3828
}
3829
+ APPS_PLUGIN_FUNCTIONS();
3830
3831
#ifdef __FreeBSD__
3832
fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'blocks/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
3834
if(unlikely(w->exposed))
3835
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
3836
}
3837
+ APPS_PLUGIN_FUNCTIONS();
3838
3839
fprintf(stdout, "CHART %s.pwrites '' '%s Disk Writes' 'blocks/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every);
3840
for (w = root; w ; w = w->next) {
3841
if(unlikely(w->exposed))
3842
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, RATES_DETAIL);
3843
}
3844
+ APPS_PLUGIN_FUNCTIONS();
3845
#else
3846
fprintf(stdout, "CHART %s.preads '' '%s Disk Reads' 'KiB/s' disk %s.preads stacked 20002 %d\n", type, title, type, update_every);
3847
for (w = root; w ; w = w->next) {
3848
if(unlikely(w->exposed))
3849
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
3850
}
3851
+ APPS_PLUGIN_FUNCTIONS();
3852
3853
fprintf(stdout, "CHART %s.pwrites '' '%s Disk Writes' 'KiB/s' disk %s.pwrites stacked 20002 %d\n", type, title, type, update_every);
3854
for (w = root; w ; w = w->next) {
3855
if(unlikely(w->exposed))
3856
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
3857
}
3858
+ APPS_PLUGIN_FUNCTIONS();
3859
3860
fprintf(stdout, "CHART %s.lreads '' '%s Disk Logical Reads' 'KiB/s' disk %s.lreads stacked 20042 %d\n", type, title, type, update_every);
3861
for (w = root; w ; w = w->next) {
3862
if(unlikely(w->exposed))
3863
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
3864
}
3865
+ APPS_PLUGIN_FUNCTIONS();
3866
3867
fprintf(stdout, "CHART %s.lwrites '' '%s I/O Logical Writes' 'KiB/s' disk %s.lwrites stacked 20042 %d\n", type, title, type, update_every);
3868
for (w = root; w ; w = w->next) {
3869
if(unlikely(w->exposed))
3870
fprintf(stdout, "DIMENSION %s '' absolute 1 %llu\n", w->name, 1024LLU * RATES_DETAIL);
3871
}
3872
+ APPS_PLUGIN_FUNCTIONS();
3873
#endif
3874
3875
if(enable_file_charts) {
3879
if (unlikely(w->exposed))
3880
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3881
}
3882
+ APPS_PLUGIN_FUNCTIONS();
3883
3884
fprintf(stdout, "CHART %s.sockets '' '%s Open Sockets' 'open sockets' net %s.sockets stacked 20051 %d\n",
3885
type, title, type, update_every);
3887
if (unlikely(w->exposed))
3888
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3889
}
3890
+ APPS_PLUGIN_FUNCTIONS();
3891
3892
fprintf(stdout, "CHART %s.pipes '' '%s Pipes' 'open pipes' processes %s.pipes stacked 20053 %d\n", type,
3893
title, type, update_every);
3895
if (unlikely(w->exposed))
3896
fprintf(stdout, "DIMENSION %s '' absolute 1 1\n", w->name);
3897
}
3898
+ APPS_PLUGIN_FUNCTIONS();
3899
}
3900
}
3901
4174
}
4175
#endif
4176
4177
+netdata_mutex_t mutex = NETDATA_MUTEX_INITIALIZER;
4178
+
4179
+#define PROCESS_FILTER_CATEGORY "category:"
4180
+#define PROCESS_FILTER_USER "user:"
4181
+#define PROCESS_FILTER_GROUP "group:"
4182
+#define PROCESS_FILTER_PROCESS "process:"
4183
+#define PROCESS_FILTER_PID "pid:"
4184
+#define PROCESS_FILTER_UID "uid:"
4185
+#define PROCESS_FILTER_GID "gid:"
4186
+
4187
+static struct target *find_target_by_name(struct target *base, const char *name) {
4188
+ struct target *t;
4189
+ for(t = base; t ; t = t->next) {
4190
+ if (strcmp(t->name, name) == 0)
4191
+ return t;
4192
+ }
4193
+
4194
+ return NULL;
4195
+}
4196
+
4197
+static kernel_uint_t MemTotal = 0;
4198
+
4199
+static void get_MemTotal(void) {
4200
+#ifdef __FreeBSD__
4201
+ // TODO - fix this for FreeBSD
4202
+ return;
4203
+#else
4204
+ char filename[FILENAME_MAX + 1];
4205
+ snprintfz(filename, FILENAME_MAX, "%s/proc/meminfo", netdata_configured_host_prefix);
4206
+
4207
+ procfile *ff = procfile_open(filename, ": \t", PROCFILE_FLAG_DEFAULT);
4208
+ if(!ff)
4209
+ return;
4210
+
4211
+ ff = procfile_readall(ff);
4212
+ if(!ff)
4213
+ return;
4214
+
4215
+ size_t line, lines = procfile_lines(ff);
4216
+
4217
+ for(line = 0; line < lines ;line++) {
4218
+ size_t words = procfile_linewords(ff, line);
4219
+ if(words == 3 && strcmp(procfile_lineword(ff, line, 0), "MemTotal") == 0 && strcmp(procfile_lineword(ff, line, 2), "kB") == 0) {
4220
+ kernel_uint_t n = str2ull(procfile_lineword(ff, line, 1));
4221
+ if(n) MemTotal = n;
4222
+ break;
4223
+ }
4224
+ }
4225
+
4226
+ procfile_close(ff);
4227
+#endif
4228
+}
4229
+
4230
+static void apps_plugin_function_error(const char *transaction, int code, const char *msg) {
4231
+ char buffer[PLUGINSD_LINE_MAX + 1];
4232
+ json_escape_string(buffer, msg, PLUGINSD_LINE_MAX);
4233
+
4234
+ pluginsd_function_result_begin_to_stdout(transaction, code, "application/json", now_realtime_sec());
4235
+ fprintf(stdout, "{\"status\":%d,\"error_message\":\"%s\"}", code, buffer);
4236
+ pluginsd_function_result_end_to_stdout();
4237
+}
4238
+
4239
+static void apps_plugin_function_processes_help(const char *transaction) {
4240
+ pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "text/plain", now_realtime_sec() + 3600);
4241
+ fprintf(stdout, "%s",
4242
+ "apps.plugin / processes\n"
4243
+ "\n"
4244
+ "Function `processes` presents all the currently running processes of the system.\n"
4245
+ "\n"
4246
+ "The following filters are supported:\n"
4247
+ "\n"
4248
+ " category:NAME\n"
4249
+ " Shows only processes that are assigned the category `NAME` in apps_groups.conf\n"
4250
+ "\n"
4251
+ " user:NAME\n"
4252
+ " Shows only processes that are running as user name `NAME`.\n"
4253
+ "\n"
4254
+ " group:NAME\n"
4255
+ " Shows only processes that are running as group name `NAME`.\n"
4256
+ "\n"
4257
+ " process:NAME\n"
4258
+ " Shows only processes that their Command is `NAME` or their parent's Command is `NAME`.\n"
4259
+ "\n"
4260
+ " pid:NUMBER\n"
4261
+ " Shows only processes that their PID is `NUMBER` or their parent's PID is `NUMBER`\n"
4262
+ "\n"
4263
+ " uid:NUMBER\n"
4264
+ " Shows only processes that their UID is `NUMBER`\n"
4265
+ "\n"
4266
+ " gid:NUMBER\n"
4267
+ " Shows only processes that their GID is `NUMBER`\n"
4268
+ "\n"
4269
+ "Filters can be combined. Each filter can be given only one time.\n"
4270
+ );
4271
+ pluginsd_function_result_end_to_stdout();
4272
+}
4273
+
4274
+#define add_table_field(wb, key, name, visible, type, units, max, sort) do { \
4275
+ if(fields_added) buffer_strcat(wb, ","); \
4276
+ buffer_sprintf(wb, "\n \"%s\": {", key); \
4277
+ buffer_sprintf(wb, "\n \"index\":%d,", fields_added); \
4278
+ buffer_sprintf(wb, "\n \"name\":\"%s\",", name); \
4279
+ buffer_sprintf(wb, "\n \"visible\":%s,", (visible)?"true":"false"); \
4280
+ buffer_sprintf(wb, "\n \"type\":\"%s\",", type); \
4281
+ if(units) \
4282
+ buffer_sprintf(wb, "\n \"units\":\"%s\",", (char*)(units)); \
4283
+ if(!isnan(max)) \
4284
+ buffer_sprintf(wb, "\n \"max\":\"%f\",", (NETDATA_DOUBLE)(max)); \
4285
+ buffer_sprintf(wb, "\n \"sort\":\"%s\"", sort); \
4286
+ buffer_sprintf(wb, "\n }"); \
4287
+ fields_added++; \
4288
+ } while(0)
4289
+
4290
+static BUFFER *func_processes_fields = NULL;
4291
+
4292
+static void apps_plugin_function_processes(const char *transaction, char *function __maybe_unused, char *line_buffer __maybe_unused, int line_max __maybe_unused, int timeout __maybe_unused) {
4293
+ struct pid_stat *p;
4294
+
4295
+ char *words[PLUGINSD_MAX_WORDS] = { NULL };
4296
+ pluginsd_split_words(function, words, PLUGINSD_MAX_WORDS, NULL, NULL, 0);
4297
+
4298
+ struct target *category = NULL, *user = NULL, *group = NULL;
4299
+ const char *process_name = NULL;
4300
+ pid_t pid = 0;
4301
+ uid_t uid = 0;
4302
+ gid_t gid = 0;
4303
+
4304
+ bool filter_pid = false, filter_uid = false, filter_gid = false;
4305
+
4306
+ for(int i = 1; i < PLUGINSD_MAX_WORDS ;i++) {
4307
+ if(!words[i]) break;
4308
+
4309
+ if(!category && strncmp(words[i], PROCESS_FILTER_CATEGORY, strlen(PROCESS_FILTER_CATEGORY)) == 0) {
4310
+ category = find_target_by_name(apps_groups_root_target, &words[i][strlen(PROCESS_FILTER_CATEGORY)]);
4311
+ if(!category) {
4312
+ apps_plugin_function_error(transaction, HTTP_RESP_BAD_REQUEST, "No category with that name found.");
4313
+ return;
4314
+ }
4315
+ }
4316
+ else if(!user && strncmp(words[i], PROCESS_FILTER_USER, strlen(PROCESS_FILTER_USER)) == 0) {
4317
+ user = find_target_by_name(users_root_target, &words[i][strlen(PROCESS_FILTER_USER)]);
4318
+ if(!user) {
4319
+ apps_plugin_function_error(transaction, HTTP_RESP_BAD_REQUEST, "No user with that name found.");
4320
+ return;
4321
+ }
4322
+ }
4323
+ else if(strncmp(words[i], PROCESS_FILTER_GROUP, strlen(PROCESS_FILTER_GROUP)) == 0) {
4324
+ group = find_target_by_name(groups_root_target, &words[i][strlen(PROCESS_FILTER_GROUP)]);
4325
+ if(!group) {
4326
+ apps_plugin_function_error(transaction, HTTP_RESP_BAD_REQUEST, "No group with that name found.");
4327
+ return;
4328
+ }
4329
+ }
4330
+ else if(!process_name && strncmp(words[i], PROCESS_FILTER_PROCESS, strlen(PROCESS_FILTER_PROCESS)) == 0) {
4331
+ process_name = &words[i][strlen(PROCESS_FILTER_PROCESS)];
4332
+ }
4333
+ else if(!pid && strncmp(words[i], PROCESS_FILTER_PID, strlen(PROCESS_FILTER_PID)) == 0) {
4334
+ pid = str2i(&words[i][strlen(PROCESS_FILTER_PID)]);
4335
+ filter_pid = true;
4336
+ }
4337
+ else if(!uid && strncmp(words[i], PROCESS_FILTER_UID, strlen(PROCESS_FILTER_UID)) == 0) {
4338
+ uid = str2i(&words[i][strlen(PROCESS_FILTER_UID)]);
4339
+ filter_uid = true;
4340
+ }
4341
+ else if(!gid && strncmp(words[i], PROCESS_FILTER_GID, strlen(PROCESS_FILTER_GID)) == 0) {
4342
+ gid = str2i(&words[i][strlen(PROCESS_FILTER_GID)]);
4343
+ filter_gid = true;
4344
+ }
4345
+ else if(strcmp(words[i], "help") == 0) {
4346
+ apps_plugin_function_processes_help(transaction);
4347
+ return;
4348
+ }
4349
+ else {
4350
+ char msg[PLUGINSD_LINE_MAX];
4351
+ snprintfz(msg, PLUGINSD_LINE_MAX, "Invalid parameter '%s'", words[i]);
4352
+ apps_plugin_function_error(transaction, HTTP_RESP_BAD_REQUEST, msg);
4353
+ return;
4354
+ }
4355
+ }
4356
+
4357
+ time_t expires = now_realtime_sec() + update_every;
4358
+ pluginsd_function_result_begin_to_stdout(transaction, HTTP_RESP_OK, "application/json", expires);
4359
+
4360
+ if(unlikely(!func_processes_fields)) {
4361
+ func_processes_fields = buffer_create(1000);
4362
+
4363
+ int fields_added = 0;
4364
+
4365
+ buffer_sprintf(func_processes_fields,
4366
+ "{"
4367
+ "\n \"status\":%d"
4368
+ ",\n \"type\":\"table\""
4369
+ ",\n \"update_every\":%d"
4370
+ ",\n \"columns\": {"
4371
+ , HTTP_RESP_OK
4372
+ , update_every
4373
+ );
4374
+
4375
+ // IMPORTANT!
4376
+ // THE ORDER SHOULD BE THE SAME WITH THE VALUES!
4377
+
4378
+ add_table_field(func_processes_fields, "Pid", "Process ID", true, "integer", NULL, NAN, "ascending");
4379
+ add_table_field(func_processes_fields, "Cmd", "Process Name", true, "string", NULL, NAN, "ascending");
4380
+
4381
+#ifdef NETDATA_DEV_MODE
4382
+ add_table_field(func_processes_fields, "CmdLine", "Command Line", false, "detail-string:cmd", NULL, NAN, "ascending");
4383
+#endif
4384
+ add_table_field(func_processes_fields, "PPid", "Parent Process ID", false, "integer", NULL, NAN, "ascending");
4385
+ add_table_field(func_processes_fields, "Category", "Category (apps_groups.conf)", true, "string", NULL, NAN, "ascending");
4386
+ add_table_field(func_processes_fields, "User", "User Owner", true, "string", NULL, NAN, "ascending");
4387
+ add_table_field(func_processes_fields, "Uid", "User ID", false, "integer", NULL, NAN, "ascending");
4388
+ add_table_field(func_processes_fields, "Group", "Group Owner", false, "string", NULL, NAN, "ascending");
4389
+ add_table_field(func_processes_fields, "Gid", "Group ID", false, "integer", NULL, NAN, "ascending");
4390
+ add_table_field(func_processes_fields, "Processes", "Processes", true, "bar-with-integer", "processes", NAN, "descending");
4391
+ add_table_field(func_processes_fields, "Threads", "Threads", true, "bar-with-integer", "threads", NAN, "descending");
4392
+ add_table_field(func_processes_fields, "Uptime", "Uptime in seconds", true, "duration", "seconds", NAN, "descending");
4393
+
4394
+ // minor page faults
4395
+ add_table_field(func_processes_fields, "MinFlt", "Minor Page Faults/s", false, "bar", "page faults/s", NAN, "descending");
4396
+ add_table_field(func_processes_fields, "CMinFlt", "Children Minor Page Faults/s", false, "bar", "page faults/s", NAN, "descending");
4397
+ add_table_field(func_processes_fields, "TMinFlt", "Total Minor Page Faults/s", false, "bar", "page faults/s", NAN, "descending");
4398
+
4399
+ // major page faults
4400
+ add_table_field(func_processes_fields, "MajFlt", "Major Page Faults/s", false, "bar", "page faults/s", NAN, "descending");
4401
+ add_table_field(func_processes_fields, "CMajFlt", "Children Major Page Faults/s", false, "bar", "page faults/s", NAN, "descending");
4402
+ add_table_field(func_processes_fields, "TMajFlt", "Total Major Page Faults/s", true, "bar", "page faults/s", NAN, "descending");
4403
+
4404
+ // CPU utilization
4405
+ add_table_field(func_processes_fields, "UserCPU", "User CPU time", false, "bar-only", "%", NAN, "descending");
4406
+ add_table_field(func_processes_fields, "SysCPU", "System CPU Time", false, "bar-only", "%", NAN, "descending");
4407
+ add_table_field(func_processes_fields, "GuestCPU", "Guest CPU Time", false, "bar-only", "%", NAN, "descending");
4408
+ add_table_field(func_processes_fields, "CUserCPU", "Children User CPU Time", false, "bar-only", "%", NAN, "descending");
4409
+ add_table_field(func_processes_fields, "CSysCPU", "Children System CPU Time", false, "bar-only", "%", NAN, "descending");
4410
+ add_table_field(func_processes_fields, "CGuestCPU", "Children Guest CPU Time", false, "bar-only", "%", NAN, "descending");
4411
+ add_table_field(func_processes_fields, "CPU", "Total CPU Time", true, "bar-only", "%", NAN, "descending");
4412
+
4413
+ // memory
4414
+ add_table_field(func_processes_fields, "VMSize", "Virtual Memory Size", false, "bar", "MiB", NAN, "descending");
4415
+ add_table_field(func_processes_fields, "RSS", "Resident Set Size", MemTotal?false:true, "bar", "MiB", NAN, "descending");
4416
+ add_table_field(func_processes_fields, "Shared", "Shared Pages", false, "bar", "MiB", NAN, "descending");
4417
+ add_table_field(func_processes_fields, "Swap", "Swap Memory", false, "bar", "MiB", NAN, "descending");
4418
+
4419
+ if(MemTotal)
4420
+ add_table_field(func_processes_fields, "MemPcnt", "Memory Percentage", true, "bar", "%", 100.0, "descending");
4421
+
4422
+ // Logical I/O
4423
+#ifndef __FreeBSD__
4424
+ add_table_field(func_processes_fields, "LReads", "Logical I/O Reads", false, "bar", "KiB/s", NAN, "descending");
4425
+ add_table_field(func_processes_fields, "LWrites", "Logical I/O Writes", false, "bar", "KiB/s", NAN, "descending");
4426
+#endif
4427
+
4428
+ // Physical I/O
4429
+ add_table_field(func_processes_fields, "PReads", "Physical I/O Reads", true, "bar", "KiB/s", NAN, "descending");
4430
+ add_table_field(func_processes_fields, "PWrites", "Physical I/O Writes", true, "bar", "KiB/s", NAN, "descending");
4431
+
4432
+ // I/O calls
4433
+ add_table_field(func_processes_fields, "RCalls", "I/O Read Calls", false, "bar", "calls/s", NAN, "descending");
4434
+ add_table_field(func_processes_fields, "WCalls", "I/O Write Calls", false, "bar", "calls/s", NAN, "descending");
4435
+
4436
+ // open file descriptors
4437
+ add_table_field(func_processes_fields, "Files", "Open Files", false, "bar", "generic", NAN, "descending");
4438
+ add_table_field(func_processes_fields, "Pipes", "Open Pipes", false, "bar", "generic", NAN, "descending");
4439
+ add_table_field(func_processes_fields, "Sockets", "Open Sockets", false, "bar", "generic", NAN, "descending");
4440
+ add_table_field(func_processes_fields, "iNotiFDs", "Open iNotify Descriptors", false, "bar", "generic", NAN, "descending");
4441
+ add_table_field(func_processes_fields, "EventFDs", "Open Event Descriptors", false, "bar", "generic", NAN, "descending");
4442
+ add_table_field(func_processes_fields, "TimerFDs", "Open Timer Descriptors", false, "bar", "generic", NAN, "descending");
4443
+ add_table_field(func_processes_fields, "SigFDs", "Open Signal Descriptors", false, "bar", "generic", NAN, "descending");
4444
+ add_table_field(func_processes_fields, "EvPollFDs", "Open Event Poll Descriptors", false, "bar", "generic", NAN, "descending");
4445
+ add_table_field(func_processes_fields, "OtherFDs", "Other Open Descriptors", false, "bar", "generic", NAN, "descending");
4446
+ add_table_field(func_processes_fields, "FDs", "All Open File Descriptors", true, "bar", "generic", NAN, "descending");
4447
+
4448
+ buffer_strcat(
4449
+ func_processes_fields,
4450
+ ""
4451
+ "\n },"
4452
+ "\n \"default sort column\": \"CPU\","
4453
+ "\n \"charts\": {"
4454
+ "\n \"CPU\": {"
4455
+ "\n \"name\":\"CPU Utilization\","
4456
+ "\n \"type\":\"stacked-bar\","
4457
+ "\n \"columns\": [ \"UserCPU\", \"SysCPU\", \"GuestCPU\", \"CUserCPU\", \"CSysCPU\", \"CGuestCPU\" ]"
4458
+ "\n },"
4459
+ "\n \"Memory\": {"
4460
+ "\n \"name\":\"Memory\","
4461
+ "\n \"type\":\"stacked-bar\","
4462
+ "\n \"columns\": [ \"VMSize\", \"RSS\", \"Shared\", \"Swap\" ]"
4463
+ "\n },"
4464
+ );
4465
+
4466
+ if(MemTotal)
4467
+ buffer_strcat(
4468
+ func_processes_fields,
4469
+ ""
4470
+ "\n \"MemoryPercent\": {"
4471
+ "\n \"name\":\"Memory Percentage\","
4472
+ "\n \"type\":\"stacked-bar\","
4473
+ "\n \"columns\": [ \"MemPcnt\" ]"
4474
+ "\n },"
4475
+ );
4476
+
4477
+ buffer_strcat(
4478
+ func_processes_fields, ""
4479
+#ifndef __FreeBSD__
4480
+ "\n \"Reads\": {"
4481
+ "\n \"name\":\"I/O Reads\","
4482
+ "\n \"type\":\"stacked-bar\","
4483
+ "\n \"columns\": [ \"LReads\", \"PReads\" ]"
4484
+ "\n },"
4485
+ "\n \"Writes\": {"
4486
+ "\n \"name\":\"I/O Writes\","
4487
+ "\n \"type\":\"stacked-bar\","
4488
+ "\n \"columns\": [ \"LWrites\", \"PWrites\" ]"
4489
+ "\n },"
4490
+ "\n \"LogicalIO\": {"
4491
+ "\n \"name\":\"Logical I/O\","
4492
+ "\n \"type\":\"stacked-bar\","
4493
+ "\n \"columns\": [ \"LReads\", \"LWrites\" ]"
4494
+ "\n },"
4495
+#endif
4496
+ "\n \"PhysicalIO\": {"
4497
+ "\n \"name\":\"Physical I/O\","
4498
+ "\n \"type\":\"stacked-bar\","
4499
+ "\n \"columns\": [ \"PReads\", \"PWrites\" ]"
4500
+ "\n },"
4501
+ "\n \"IOCalls\": {"
4502
+ "\n \"name\":\"I/O Calls\","
4503
+ "\n \"type\":\"stacked-bar\","
4504
+ "\n \"columns\": [ \"RCalls\", \"WCalls\" ]"
4505
+ "\n },"
4506
+ "\n \"MinFlt\": {"
4507
+ "\n \"name\":\"Minor Page Faults\","
4508
+ "\n \"type\":\"stacked-bar\","
4509
+ "\n \"columns\": [ \"MinFlt\", \"CMinFlt\" ]"
4510
+ "\n },"
4511
+ "\n \"MajFlt\": {"
4512
+ "\n \"name\":\"Major Page Faults\","
4513
+ "\n \"type\":\"stacked-bar\","
4514
+ "\n \"columns\": [ \"MajFlt\", \"CMajFlt\" ]"
4515
+ "\n },"
4516
+ "\n \"Threads\": {"
4517
+ "\n \"name\":\"Threads\","
4518
+ "\n \"type\":\"stacked-bar\","
4519
+ "\n \"columns\": [ \"Threads\" ]"
4520
+ "\n },"
4521
+ "\n \"Processes\": {"
4522
+ "\n \"name\":\"Processes\","
4523
+ "\n \"type\":\"stacked-bar\","
4524
+ "\n \"columns\": [ \"Processes\" ]"
4525
+ "\n },"
4526
+ "\n \"FDs\": {"
4527
+ "\n \"name\":\"File Descriptors\","
4528
+ "\n \"type\":\"stacked-bar\","
4529
+ "\n \"columns\": [ \"Files\", \"Pipes\", \"Sockets\", \"iNotiFDs\", \"EventFDs\", \"TimerFDs\", \"SigFDs\", \"EvPollFDs\", \"OtherFDs\" ]"
4530
+ "\n }"
4531
+ "\n },"
4532
+ "\n \"group_by\": {"
4533
+ "\n \"Process Tree by PID\": {"
4534
+ "\n \"columns\": [ \"PPid\", \"Pid\" ],"
4535
+ "\n \"order\": [ \"ascending\", \"ascending\" ]"
4536
+ "\n },"
4537
+ "\n \"Process Tree by Category\": {"
4538
+ "\n \"columns\": [ \"Category\", \"PPid\", \"Pid\" ],"
4539
+ "\n \"order\": [ \"any\", \"ascending\", \"ascending\" ]"
4540
+ "\n }"
4541
+ "\n },"
4542
+ "\n \"data\":["
4543
+ "\n"
4544
+ );
4545
+ }
4546
+
4547
+ fwrite(buffer_tostring(func_processes_fields), buffer_strlen(func_processes_fields), 1, stdout);
4548
+
4549
+ unsigned int cpu_divisor = time_factor * RATES_DETAIL / 100;
4550
+ unsigned int memory_divisor = 1024;
4551
+ unsigned int io_divisor = 1024 * RATES_DETAIL;
4552
+
4553
+ BUFFER *wb = buffer_create(PLUGINSD_LINE_MAX);
4554
+
4555
+ int rows= 0;
4556
+ for(p = root_of_pids; p ; p = p->next) {
4557
+ if(!p->updated)
4558
+ continue;
4559
+
4560
+ if(category && p->target != category)
4561
+ continue;
4562
+
4563
+ if(user && p->user_target != user)
4564
+ continue;
4565
+
4566
+ if(group && p->group_target != group)
4567
+ continue;
4568
+
4569
+ if(process_name && ((strcmp(p->comm, process_name) != 0 && !p->parent) || (p->parent && strcmp(p->comm, process_name) != 0 && strcmp(p->parent->comm, process_name) != 0)))
4570
+ continue;
4571
+
4572
+ if(filter_pid && p->pid != pid && p->ppid != pid)
4573
+ continue;
4574
+
4575
+ if(filter_uid && p->uid != uid)
4576
+ continue;
4577
+
4578
+ if(filter_gid && p->gid != gid)
4579
+ continue;
4580
+
4581
+ if(rows) buffer_fast_strcat(wb, ",\n", 2);
4582
+ rows++;
4583
+
4584
+ buffer_strcat(wb, " [");
4585
+
4586
+ // IMPORTANT!
4587
+ // THE ORDER SHOULD BE THE SAME WITH THE FIELDS!
4588
+
4589
+ // pid
4590
+ buffer_print_llu(wb, p->pid);
4591
+
4592
+ // cmd
4593
+ buffer_fast_strcat(wb, ",\"", 2);
4594
+ buffer_strcat_jsonescape(wb, p->comm);
4595
+ buffer_fast_strcat(wb, "\"", 1);
4596
+
4597
+#ifdef NETDATA_DEV_MODE
4598
+ // cmdline
4599
+ buffer_fast_strcat(wb, ",\"", 2);
4600
+ buffer_strcat_jsonescape(wb, (p->cmdline && *p->cmdline) ? p->cmdline : p->comm);
4601
+ buffer_fast_strcat(wb, "\"", 1);
4602
+#endif
4603
+
4604
+ // ppid
4605
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->ppid);
4606
+
4607
+ // category
4608
+ buffer_fast_strcat(wb, ",\"", 2);
4609
+ buffer_strcat_jsonescape(wb, p->target ? p->target->name : "-");
4610
+ buffer_fast_strcat(wb, "\"", 1);
4611
+
4612
+ // user
4613
+ buffer_fast_strcat(wb, ",\"", 2);
4614
+ buffer_strcat_jsonescape(wb, p->user_target ? p->user_target->name : "-");
4615
+ buffer_fast_strcat(wb, "\"", 1);
4616
+
4617
+ // uid
4618
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->uid);
4619
+
4620
+ // group
4621
+ buffer_fast_strcat(wb, ",\"", 2);
4622
+ buffer_strcat_jsonescape(wb, p->group_target ? p->group_target->name : "-");
4623
+ buffer_fast_strcat(wb, "\"", 1);
4624
+
4625
+ // gid
4626
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->gid);
4627
+
4628
+ // procs
4629
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->children_count);
4630
+
4631
+ // threads
4632
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->num_threads);
4633
+
4634
+ // uptime
4635
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->uptime);
4636
+
4637
+ // minor page faults
4638
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->minflt / RATES_DETAIL);
4639
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->cminflt / RATES_DETAIL);
4640
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, (p->minflt + p->cminflt) / RATES_DETAIL);
4641
+
4642
+ // major page faults
4643
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->majflt / RATES_DETAIL);
4644
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->cmajflt / RATES_DETAIL);
4645
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, (p->majflt + p->cmajflt) / RATES_DETAIL);
4646
+
4647
+ // CPU utilization %
4648
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)(p->utime) / cpu_divisor);
4649
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)(p->stime) / cpu_divisor);
4650
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)(p->gtime) / cpu_divisor);
4651
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)(p->cutime) / cpu_divisor);
4652
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)(p->cstime) / cpu_divisor);
4653
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)(p->cgtime) / cpu_divisor);
4654
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)(p->utime + p->stime + p->gtime + p->cutime + p->cstime + p->cgtime) / cpu_divisor);
4655
+
4656
+ // memory MiB
4657
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)p->status_vmsize / memory_divisor);
4658
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)p->status_vmrss / memory_divisor);
4659
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)p->status_vmshared / memory_divisor);
4660
+ buffer_fast_strcat(wb, ",", 1); buffer_rrd_value(wb, (NETDATA_DOUBLE)p->status_vmswap / memory_divisor);
4661
+
4662
+ if(MemTotal) {
4663
+ buffer_fast_strcat(wb, ",", 1);
4664
+ buffer_rrd_value(wb, (NETDATA_DOUBLE)p->status_vmrss * 100.0 / (NETDATA_DOUBLE)MemTotal);
4665
+ }
4666
+
4667
+ // Logical I/O
4668
+#ifndef __FreeBSD__
4669
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->io_logical_bytes_read / io_divisor);
4670
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->io_logical_bytes_written / io_divisor);
4671
+#endif
4672
+
4673
+ // Physical I/O
4674
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->io_storage_bytes_read / io_divisor);
4675
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->io_storage_bytes_written / io_divisor);
4676
+
4677
+ // I/O calls
4678
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->io_read_calls / RATES_DETAIL);
4679
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->io_write_calls / RATES_DETAIL);
4680
+
4681
+ // open file descriptors
4682
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.files);
4683
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.pipes);
4684
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.sockets);
4685
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.inotifies);
4686
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.eventfds);
4687
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.timerfds);
4688
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.signalfds);
4689
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.eventpolls);
4690
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.other);
4691
+ buffer_fast_strcat(wb, ",", 1); buffer_print_llu(wb, p->openfds.files + p->openfds.pipes + p->openfds.sockets + p->openfds.inotifies + p->openfds.eventfds + p->openfds.timerfds + p->openfds.signalfds + p->openfds.eventpolls + p->openfds.other);
4692
+
4693
+ buffer_fast_strcat(wb, "]", 1);
4694
+
4695
+ fwrite(buffer_tostring(wb), buffer_strlen(wb), 1, stdout);
4696
+ buffer_flush(wb);
4697
+ }
4698
+
4699
+ buffer_free(wb);
4700
+
4701
+ fprintf(stdout, "\n ]");
4702
+ fprintf(stdout, ",\n \"expires\":%ld", expires);
4703
+ fprintf(stdout, "\n}");
4704
+
4705
+ pluginsd_function_result_end_to_stdout();
4706
+}
4707
+
4708
+bool apps_plugin_exit = false;
4709
+
4710
+void *reader_main(void *arg __maybe_unused) {
4711
+ char buffer[PLUGINSD_LINE_MAX + 1];
4712
+
4713
+ char *s = NULL;
4714
+ while(!apps_plugin_exit && (s = fgets(buffer, PLUGINSD_LINE_MAX, stdin))) {
4715
+
4716
+ char *words[PLUGINSD_MAX_WORDS] = { NULL };
4717
+ pluginsd_split_words(buffer, words, PLUGINSD_MAX_WORDS, NULL, NULL, 0);
4718
+
4719
+ if(words[0] && strcmp(words[0], PLUGINSD_KEYWORD_FUNCTION) == 0) {
4720
+ char *transaction = words[1];
4721
+ char *timeout_s = words[2];
4722
+ char *function = words[3];
4723
+
4724
+ if(!transaction || !*transaction || !timeout_s || !*timeout_s || !function || !*function) {
4725
+ error("Received incomplete %s (transaction = '%s', timeout = '%s', function = '%s'). Ignoring it.",
4726
+ words[0],
4727
+ transaction?transaction:"(unset)",
4728
+ timeout_s?timeout_s:"(unset)",
4729
+ function?function:"(unset)");
4730
+ }
4731
+ else {
4732
+ int timeout = str2i(timeout_s);
4733
+ if(timeout <= 0) timeout = PLUGINS_FUNCTIONS_TIMEOUT_DEFAULT;
4734
+
4735
+// internal_error(true, "Received function '%s', transaction '%s', timeout %d", function, transaction, timeout);
4736
+
4737
+ netdata_mutex_lock(&mutex);
4738
+
4739
+ if(strncmp(function, "processes", strlen("processes")) == 0)
4740
+ apps_plugin_function_processes(transaction, function, buffer, PLUGINSD_LINE_MAX + 1, timeout);
4741
+ else
4742
+ apps_plugin_function_error(transaction, HTTP_RESP_NOT_FOUND, "No function with this name found in apps.plugin.");
4743
+
4744
+ fflush(stdout);
4745
+ netdata_mutex_unlock(&mutex);
4746
+
4747
+// internal_error(true, "Done with function '%s', transaction '%s', timeout %d", function, transaction, timeout);
4748
+ }
4749
+ }
4750
+ else
4751
+ error("Received unknown command: %s", words[0]?words[0]:"(unset)");
4752
+ }
4753
+
4754
+ if(!s || feof(stdin) || ferror(stdin)) {
4755
+ apps_plugin_exit = true;
4756
+ error("Received error on stdin.");
4757
+ }
4758
+
4759
+ exit(1);
4760
+ return NULL;
4761
+}
4762
+
4763
int main(int argc, char **argv) {
4764
// debug_flags = D_PROCFILE;
4765
4850
debug_log("group file: '%s'", all_group_ids.filename);
4851
4852
#if (ALL_PIDS_ARE_READ_INSTANTLY == 0)
4227
- all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max);
4853
+ all_pids_sortlist = callocz(sizeof(pid_t), (size_t)pid_max + 1);
4854
#endif
4855
4230
- all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max);
4856
+ all_pids = callocz(sizeof(struct pid_stat *), (size_t) pid_max + 1);
4857
+
4858
+ netdata_thread_t reader_thread;
4859
+ netdata_thread_create(&reader_thread, "APPS_READER", NETDATA_THREAD_OPTION_DONT_LOG, reader_main, NULL);
4860
+ netdata_mutex_lock(&mutex);
4861
4862
usec_t step = update_every * USEC_PER_SEC;
4863
global_iterations_counter = 1;
4864
heartbeat_t hb;
4865
heartbeat_init(&hb);
4236
- for(;1; global_iterations_counter++) {
4866
+ for(; !apps_plugin_exit ; global_iterations_counter++) {
4867
+ netdata_mutex_unlock(&mutex);
4868
4869
#ifdef NETDATA_PROFILING
4870
#warning "compiling for profiling"
4875
#else
4876
usec_t dt = heartbeat_next(&hb, step);
4877
#endif
4878
+ netdata_mutex_lock(&mutex);
4879
4880
struct pollfd pollfd = { .fd = fileno(stdout), .events = POLLERR };
4249
- if (unlikely(poll(&pollfd, 1, 0) < 0))
4881
+ if (unlikely(poll(&pollfd, 1, 0) < 0)) {
4882
+ netdata_mutex_unlock(&mutex);
4883
+ netdata_thread_cancel(reader_thread);
4884
fatal("Cannot check if a pipe is available");
4251
- if (unlikely(pollfd.revents & POLLERR))
4252
- fatal("Cannot write to a pipe");
4885
+ }
4886
+ if (unlikely(pollfd.revents & POLLERR)) {
4887
+ netdata_mutex_unlock(&mutex);
4888
+ netdata_thread_cancel(reader_thread);
4889
+ fatal("Received error on read pipe.");
4890
+ }
4891
+
4892
+ if(global_iterations_counter % 10 == 0)
4893
+ get_MemTotal();
4894
4895
if(!collect_data_for_all_processes()) {
4896
error("Cannot collect /proc data for running processes. Disabling apps.plugin...");
4897
printf("DISABLE\n");
4898
+ netdata_mutex_unlock(&mutex);
4899
+ netdata_thread_cancel(reader_thread);
4900
exit(1);
4901
}
4902