master
c 1,396 lines 63.2 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "apps_plugin.h"
4
5 bool enable_function_cmdline = false;
6
7 #define PROCESS_FILTER_CATEGORY "category:"
8 #define PROCESS_FILTER_USER "user:"
9 #define PROCESS_FILTER_GROUP "group:"
10 #define PROCESS_FILTER_PROCESS "process:"
11 #define PROCESS_FILTER_PID "pid:"
12 #define PROCESS_FILTER_UID "uid:"
13 #define PROCESS_FILTER_GID "gid:"
14
15 static void apps_plugin_function_processes_help(const char *transaction) {
16 BUFFER *wb = buffer_create(0, NULL);
17 buffer_sprintf(wb, "%s",
18 "apps.plugin / processes\n"
19 "\n"
20 "Function `processes` presents all the currently running processes of the system.\n"
21 "\n"
22 "The following filters are supported:\n"
23 "\n"
24 " category:NAME\n"
25 " Shows only processes that are assigned the category `NAME` in apps_groups.conf\n"
26 "\n"
27 " parent:NAME\n"
28 " Shows only processes that are aggregated under parent `NAME`\n"
29 "\n"
30 #if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
31 " user:NAME\n"
32 " Shows only processes that are running as user name `NAME`.\n"
33 "\n"
34 #endif
35 #if (PROCESSES_HAVE_GID == 1)
36 " group:NAME\n"
37 " Shows only processes that are running as group name `NAME`.\n"
38 "\n"
39 #endif
40 " process:NAME\n"
41 " Shows only processes that their Command is `NAME` or their parent's Command is `NAME`.\n"
42 "\n"
43 " pid:NUMBER\n"
44 " Shows only processes that their PID is `NUMBER` or their parent's PID is `NUMBER`\n"
45 "\n"
46 #if (PROCESSES_HAVE_UID == 1)
47 " uid:NUMBER\n"
48 " Shows only processes that their UID is `NUMBER`\n"
49 "\n"
50 #endif
51 #if (PROCESSES_HAVE_GID == 1)
52 " gid:NUMBER\n"
53 " Shows only processes that their GID is `NUMBER`\n"
54 "\n"
55 #endif
56 "Filters can be combined. Each filter can be given only one time.\n"
57 );
58
59 wb->response_code = HTTP_RESP_OK;
60 wb->content_type = CT_TEXT_PLAIN;
61 wb->expires = now_realtime_sec() + 3600;
62 pluginsd_function_result_to_stdout(transaction, wb);
63 buffer_free(wb);
64 }
65
66 #define add_value_field_llu_with_max(wb, key, value) do { \
67 unsigned long long _tmp = (value); \
68 key ## _max = (rows == 0) ? (_tmp) : MAX(key ## _max, _tmp); \
69 buffer_json_add_array_item_uint64(wb, _tmp); \
70 } while(0)
71
72 #define add_value_field_ndd_with_max(wb, key, value) do { \
73 NETDATA_DOUBLE _tmp = (value); \
74 key ## _max = (rows == 0) ? (_tmp) : MAX(key ## _max, _tmp); \
75 buffer_json_add_array_item_double(wb, _tmp); \
76 } while(0)
77
78 // Holds per-field maximums computed during the data collection loop.
79 // Passed to fp_emit_columns() so that section can live in its own function,
80 // keeping function_processes() below GCC's -fvar-tracking-assignments limit.
81 struct fp_maxvals {
82 NETDATA_DOUBLE UserCPU_max;
83 NETDATA_DOUBLE SysCPU_max;
84 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
85 NETDATA_DOUBLE GuestCPU_max;
86 #endif
87 #if (PROCESSES_HAVE_CPU_CHILDREN_TIME == 1)
88 NETDATA_DOUBLE CUserCPU_max;
89 NETDATA_DOUBLE CSysCPU_max;
90 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
91 NETDATA_DOUBLE CGuestCPU_max;
92 #endif
93 #endif
94 NETDATA_DOUBLE CPU_max;
95 NETDATA_DOUBLE VMSize_max;
96 NETDATA_DOUBLE RSS_max;
97 #if (PROCESSES_HAVE_SMAPS_ROLLUP == 1)
98 NETDATA_DOUBLE Estimated_max;
99 NETDATA_DOUBLE Pss_max;
100 NETDATA_DOUBLE PssAge_max;
101 NETDATA_DOUBLE SharedRatio_max;
102 #endif
103 #if (PROCESSES_HAVE_VMSHARED == 1)
104 NETDATA_DOUBLE Shared_max;
105 #endif
106 NETDATA_DOUBLE Swap_max;
107 #if (PROCESSES_HAVE_FDS == 1) && (PROCESSES_HAVE_PID_LIMITS == 1)
108 NETDATA_DOUBLE FDsLimitPercent_max;
109 #endif
110 unsigned long long Processes_max;
111 unsigned long long Threads_max;
112 #if (PROCESSES_HAVE_VOLCTX == 1)
113 unsigned long long VoluntaryCtxtSwitches_max;
114 #endif
115 #if (PROCESSES_HAVE_NVOLCTX == 1)
116 unsigned long long NonVoluntaryCtxtSwitches_max;
117 #endif
118 unsigned long long Uptime_max;
119 unsigned long long MinFlt_max;
120 #if (PROCESSES_HAVE_MAJFLT == 1)
121 unsigned long long MajFlt_max;
122 #endif
123 #if (PROCESSES_HAVE_CHILDREN_FLTS == 1)
124 unsigned long long CMinFlt_max;
125 unsigned long long CMajFlt_max;
126 unsigned long long TMinFlt_max;
127 unsigned long long TMajFlt_max;
128 #endif
129 #if (PROCESSES_HAVE_LOGICAL_IO == 1)
130 unsigned long long LReads_max;
131 unsigned long long LWrites_max;
132 #endif
133 #if (PROCESSES_HAVE_PHYSICAL_IO == 1)
134 unsigned long long PReads_max;
135 unsigned long long PWrites_max;
136 #endif
137 #if (PROCESSES_HAVE_IO_CALLS == 1)
138 unsigned long long ROps_max;
139 unsigned long long WOps_max;
140 #endif
141 #if (PROCESSES_HAVE_FDS == 1)
142 unsigned long long Files_max;
143 unsigned long long Pipes_max;
144 unsigned long long Sockets_max;
145 unsigned long long iNotiFDs_max;
146 unsigned long long EventFDs_max;
147 unsigned long long TimerFDs_max;
148 unsigned long long SigFDs_max;
149 unsigned long long EvPollFDs_max;
150 unsigned long long OtherFDs_max;
151 unsigned long long FDs_max;
152 #endif
153 #if (PROCESSES_HAVE_HANDLES == 1)
154 unsigned long long Handles_max;
155 #endif
156 };
157
158 static void fp_emit_columns(BUFFER *wb, struct fp_maxvals *mv, bool show_cmdline, uint64_t total_memory_bytes) {
159 buffer_json_member_add_object(wb, "columns");
160 {
161 int field_id = 0;
162
163 // IMPORTANT!
164 // THE ORDER SHOULD BE THE SAME WITH THE VALUES!
165 // wb, key, name, visible, type, visualization, transform, decimal_points, units, max, sort, sortable, sticky, unique_key, pointer_to, summary, range
166 buffer_rrdf_table_add_field(wb, field_id++, "PID", "Process ID", RRDF_FIELD_TYPE_INTEGER,
167 RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
168 RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
169 RRDF_FIELD_FILTER_MULTISELECT,
170 RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY |
171 RRDF_FIELD_OPTS_UNIQUE_KEY, NULL);
172
173 buffer_rrdf_table_add_field(wb, field_id++, "Cmd", "Process Name", RRDF_FIELD_TYPE_STRING,
174 RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
175 RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
176 RRDF_FIELD_FILTER_MULTISELECT,
177 RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
178
179 #if (PROCESSES_HAVE_COMM_AND_NAME == 1)
180 buffer_rrdf_table_add_field(wb, field_id++, "Name", "Process Friendly Name", RRDF_FIELD_TYPE_STRING,
181 RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
182 RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
183 RRDF_FIELD_FILTER_MULTISELECT,
184 RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
185 #endif
186
187 if (show_cmdline) {
188 buffer_rrdf_table_add_field(wb, field_id++, "CmdLine", "Command Line", RRDF_FIELD_TYPE_STRING,
189 RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0,
190 NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
191 RRDF_FIELD_FILTER_MULTISELECT,
192 RRDF_FIELD_OPTS_NONE, NULL);
193 }
194
195 buffer_rrdf_table_add_field(wb, field_id++, "PPID", "Parent Process ID", RRDF_FIELD_TYPE_INTEGER,
196 RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL,
197 NAN, RRDF_FIELD_SORT_ASCENDING, "PID", RRDF_FIELD_SUMMARY_COUNT,
198 RRDF_FIELD_FILTER_MULTISELECT,
199 RRDF_FIELD_OPTS_NONE, NULL);
200
201 buffer_rrdf_table_add_field(wb, field_id++, "Category", "Category (apps_groups.conf)", RRDF_FIELD_TYPE_STRING,
202 RRDF_FIELD_VISUAL_VALUE,
203 RRDF_FIELD_TRANSFORM_NONE,
204 0, NULL, NAN, RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
205 RRDF_FIELD_FILTER_MULTISELECT,
206 RRDF_FIELD_OPTS_VISIBLE | RRDF_FIELD_OPTS_STICKY, NULL);
207
208 #if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
209 buffer_rrdf_table_add_field(wb, field_id++, "User", "User Owner", RRDF_FIELD_TYPE_STRING,
210 RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
211 RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
212 RRDF_FIELD_FILTER_MULTISELECT,
213 RRDF_FIELD_OPTS_VISIBLE, NULL);
214 #endif
215 #if (PROCESSES_HAVE_UID == 1)
216 buffer_rrdf_table_add_field(wb, field_id++, "Uid", "User ID", RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE,
217 RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
218 RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
219 RRDF_FIELD_FILTER_MULTISELECT,
220 RRDF_FIELD_OPTS_NONE, NULL);
221 #endif
222
223 #if (PROCESSES_HAVE_GID == 1)
224 buffer_rrdf_table_add_field(wb, field_id++, "Group", "Group Owner", RRDF_FIELD_TYPE_STRING,
225 RRDF_FIELD_VISUAL_VALUE, RRDF_FIELD_TRANSFORM_NONE, 0, NULL, NAN,
226 RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
227 RRDF_FIELD_FILTER_MULTISELECT,
228 RRDF_FIELD_OPTS_NONE, NULL);
229 buffer_rrdf_table_add_field(wb, field_id++, "Gid", "Group ID", RRDF_FIELD_TYPE_INTEGER, RRDF_FIELD_VISUAL_VALUE,
230 RRDF_FIELD_TRANSFORM_NUMBER, 0, NULL, NAN,
231 RRDF_FIELD_SORT_ASCENDING, NULL, RRDF_FIELD_SUMMARY_COUNT,
232 RRDF_FIELD_FILTER_MULTISELECT,
233 RRDF_FIELD_OPTS_NONE, NULL);
234 #endif
235
236 // CPU utilization
237 buffer_rrdf_table_add_field(wb, field_id++, "CPU", "Total CPU Time (100% = 1 core)",
238 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
239 RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", mv->CPU_max, RRDF_FIELD_SORT_DESCENDING, NULL,
240 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
241 RRDF_FIELD_OPTS_VISIBLE, NULL);
242
243 buffer_rrdf_table_add_field(wb, field_id++, "UserCPU", "User CPU time (100% = 1 core)",
244 RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
245 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", mv->UserCPU_max,
246 RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
247 RRDF_FIELD_OPTS_NONE, NULL);
248 buffer_rrdf_table_add_field(wb, field_id++, "SysCPU", "System CPU Time (100% = 1 core)",
249 RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
250 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", mv->SysCPU_max,
251 RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
252 RRDF_FIELD_OPTS_NONE, NULL);
253 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
254 buffer_rrdf_table_add_field(wb, field_id++, "GuestCPU", "Guest CPU Time (100% = 1 core)",
255 RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
256 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", mv->GuestCPU_max,
257 RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
258 RRDF_FIELD_OPTS_NONE, NULL);
259 #endif
260 #if (PROCESSES_HAVE_CPU_CHILDREN_TIME == 1)
261 buffer_rrdf_table_add_field(wb, field_id++, "CUserCPU", "Children User CPU Time (100% = 1 core)",
262 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
263 RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", mv->CUserCPU_max, RRDF_FIELD_SORT_DESCENDING, NULL,
264 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
265 RRDF_FIELD_OPTS_NONE, NULL);
266 buffer_rrdf_table_add_field(wb, field_id++, "CSysCPU", "Children System CPU Time (100% = 1 core)",
267 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
268 RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", mv->CSysCPU_max, RRDF_FIELD_SORT_DESCENDING, NULL,
269 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
270 RRDF_FIELD_OPTS_NONE, NULL);
271 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
272 buffer_rrdf_table_add_field(wb, field_id++, "CGuestCPU", "Children Guest CPU Time (100% = 1 core)",
273 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
274 RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", mv->CGuestCPU_max, RRDF_FIELD_SORT_DESCENDING,
275 NULL,
276 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE, RRDF_FIELD_OPTS_NONE, NULL);
277 #endif
278 #endif
279
280 #if (PROCESSES_HAVE_VOLCTX == 1)
281 // CPU context switches
282 buffer_rrdf_table_add_field(wb, field_id++, "vCtxSwitch", "Voluntary Context Switches",
283 RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
284 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "switches/s",
285 mv->VoluntaryCtxtSwitches_max, RRDF_FIELD_SORT_DESCENDING, NULL,
286 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE, RRDF_FIELD_OPTS_NONE, NULL);
287 #endif
288 #if (PROCESSES_HAVE_NVOLCTX == 1)
289 buffer_rrdf_table_add_field(wb, field_id++, "iCtxSwitch", "Involuntary Context Switches",
290 RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
291 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2, "switches/s",
292 mv->NonVoluntaryCtxtSwitches_max, RRDF_FIELD_SORT_DESCENDING, NULL,
293 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE, RRDF_FIELD_OPTS_NONE, NULL);
294 #endif
295
296 // memory
297 if (total_memory_bytes)
298 buffer_rrdf_table_add_field(wb, field_id++, "Memory", "Memory Percentage", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
299 RRDF_FIELD_VISUAL_BAR,
300 RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", 100.0, RRDF_FIELD_SORT_DESCENDING, NULL,
301 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
302 RRDF_FIELD_OPTS_VISIBLE, NULL);
303
304 buffer_rrdf_table_add_field(wb, field_id++, "Resident", "Resident Set Size", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
305 RRDF_FIELD_VISUAL_BAR,
306 RRDF_FIELD_TRANSFORM_NUMBER,
307 2, "MiB", mv->RSS_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
308 RRDF_FIELD_FILTER_RANGE,
309 RRDF_FIELD_OPTS_VISIBLE, NULL);
310 #if (PROCESSES_HAVE_SMAPS_ROLLUP == 1)
311 if(pss_refresh_period > 0) {
312 buffer_rrdf_table_add_field(wb, field_id++, "Estimated", "Estimated Memory Usage", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
313 RRDF_FIELD_VISUAL_BAR,
314 RRDF_FIELD_TRANSFORM_NUMBER,
315 2, "MiB", mv->Estimated_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
316 RRDF_FIELD_FILTER_RANGE,
317 RRDF_FIELD_OPTS_VISIBLE, NULL);
318 buffer_rrdf_table_add_field(wb, field_id++, "Pss", "Proportional Set Size", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
319 RRDF_FIELD_VISUAL_BAR,
320 RRDF_FIELD_TRANSFORM_NUMBER,
321 2, "MiB", mv->Pss_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
322 RRDF_FIELD_FILTER_RANGE,
323 RRDF_FIELD_OPTS_NONE, NULL);
324 buffer_rrdf_table_add_field(wb, field_id++, "PssAge", "Time since last smaps sample", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
325 RRDF_FIELD_VISUAL_BAR,
326 RRDF_FIELD_TRANSFORM_NUMBER,
327 2, "s", mv->PssAge_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_MAX,
328 RRDF_FIELD_FILTER_RANGE,
329 RRDF_FIELD_OPTS_NONE, NULL);
330 buffer_rrdf_table_add_field(wb, field_id++, "SharedRatio", "Shared Memory Ratio", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
331 RRDF_FIELD_VISUAL_BAR,
332 RRDF_FIELD_TRANSFORM_NUMBER,
333 2, "%", mv->SharedRatio_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_MEAN,
334 RRDF_FIELD_FILTER_RANGE,
335 RRDF_FIELD_OPTS_NONE, NULL);
336 }
337 #endif
338 #if (PROCESSES_HAVE_VMSHARED == 1)
339 buffer_rrdf_table_add_field(wb, field_id++, "Shared", "Shared Pages", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
340 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2,
341 "MiB", mv->Shared_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
342 RRDF_FIELD_FILTER_RANGE,
343 RRDF_FIELD_OPTS_VISIBLE, NULL);
344 #endif
345
346 buffer_rrdf_table_add_field(wb, field_id++, "Virtual", "Virtual Memory Size", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
347 RRDF_FIELD_VISUAL_BAR,
348 RRDF_FIELD_TRANSFORM_NUMBER, 2, "MiB", mv->VMSize_max, RRDF_FIELD_SORT_DESCENDING, NULL,
349 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
350 RRDF_FIELD_OPTS_VISIBLE, NULL);
351
352 #if (PROCESSES_HAVE_VMSWAP == 1)
353 buffer_rrdf_table_add_field(wb, field_id++, "Swap", "Swap Memory", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
354 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2,
355 "MiB",
356 mv->Swap_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
357 RRDF_FIELD_FILTER_RANGE,
358 RRDF_FIELD_OPTS_NONE, NULL);
359 #endif
360
361 #if (PROCESSES_HAVE_PHYSICAL_IO == 1)
362 // Physical I/O
363 buffer_rrdf_table_add_field(wb, field_id++, "PReads", "Physical I/O Reads", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
364 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
365 2, "KiB/s", mv->PReads_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
366 RRDF_FIELD_FILTER_RANGE,
367 RRDF_FIELD_OPTS_VISIBLE, NULL);
368 buffer_rrdf_table_add_field(wb, field_id++, "PWrites", "Physical I/O Writes", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
369 RRDF_FIELD_VISUAL_BAR,
370 RRDF_FIELD_TRANSFORM_NUMBER, 2, "KiB/s", mv->PWrites_max, RRDF_FIELD_SORT_DESCENDING,
371 NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
372 RRDF_FIELD_OPTS_VISIBLE, NULL);
373 #endif
374
375 #if (PROCESSES_HAVE_LOGICAL_IO == 1)
376 #if (PROCESSES_HAVE_PHYSICAL_IO == 1)
377 RRDF_FIELD_OPTIONS logical_io_options = RRDF_FIELD_OPTS_NONE;
378 #else
379 RRDF_FIELD_OPTIONS logical_io_options = RRDF_FIELD_OPTS_VISIBLE;
380 #endif
381 // Logical I/O
382 buffer_rrdf_table_add_field(wb, field_id++, "LReads", "Logical I/O Reads", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
383 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER,
384 2, "KiB/s", mv->LReads_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
385 RRDF_FIELD_FILTER_RANGE,
386 logical_io_options, NULL);
387 buffer_rrdf_table_add_field(wb, field_id++, "LWrites", "Logical I/O Writes", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
388 RRDF_FIELD_VISUAL_BAR,
389 RRDF_FIELD_TRANSFORM_NUMBER,
390 2, "KiB/s", mv->LWrites_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
391 RRDF_FIELD_FILTER_RANGE,
392 logical_io_options, NULL);
393 #endif
394
395 #if (PROCESSES_HAVE_IO_CALLS == 1)
396 // I/O calls
397 buffer_rrdf_table_add_field(wb, field_id++, "ROps", "I/O Read Operations", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
398 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2,
399 "ops/s", mv->ROps_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
400 RRDF_FIELD_FILTER_RANGE,
401 RRDF_FIELD_OPTS_NONE, NULL);
402 buffer_rrdf_table_add_field(wb, field_id++, "WOps", "I/O Write Operations", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
403 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 2,
404 "ops/s", mv->WOps_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
405 RRDF_FIELD_FILTER_RANGE,
406 RRDF_FIELD_OPTS_NONE, NULL);
407 #endif
408
409 // minor page faults
410 buffer_rrdf_table_add_field(wb, field_id++, "MinFlt", "Minor Page Faults/s", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
411 RRDF_FIELD_VISUAL_BAR,
412 RRDF_FIELD_TRANSFORM_NUMBER,
413 2, "pgflts/s", mv->MinFlt_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
414 RRDF_FIELD_FILTER_RANGE,
415 RRDF_FIELD_OPTS_NONE, NULL);
416
417 #if (PROCESSES_HAVE_MAJFLT == 1)
418 // major page faults
419 buffer_rrdf_table_add_field(wb, field_id++, "MajFlt", "Major Page Faults/s", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
420 RRDF_FIELD_VISUAL_BAR,
421 RRDF_FIELD_TRANSFORM_NUMBER,
422 2, "pgflts/s", mv->MajFlt_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
423 RRDF_FIELD_FILTER_RANGE,
424 RRDF_FIELD_OPTS_NONE, NULL);
425 #endif
426
427 #if (PROCESSES_HAVE_CHILDREN_FLTS == 1)
428 buffer_rrdf_table_add_field(wb, field_id++, "CMinFlt", "Children Minor Page Faults/s",
429 RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
430 RRDF_FIELD_VISUAL_BAR,
431 RRDF_FIELD_TRANSFORM_NUMBER, 2, "pgflts/s", mv->CMinFlt_max, RRDF_FIELD_SORT_DESCENDING,
432 NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
433 RRDF_FIELD_OPTS_NONE, NULL);
434 buffer_rrdf_table_add_field(wb, field_id++, "CMajFlt", "Children Major Page Faults/s",
435 RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
436 RRDF_FIELD_VISUAL_BAR,
437 RRDF_FIELD_TRANSFORM_NUMBER, 2, "pgflts/s", mv->CMajFlt_max, RRDF_FIELD_SORT_DESCENDING,
438 NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
439 RRDF_FIELD_OPTS_NONE, NULL);
440 buffer_rrdf_table_add_field(wb, field_id++, "TMinFlt", "Total Minor Page Faults/s",
441 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
442 RRDF_FIELD_TRANSFORM_NUMBER, 2, "pgflts/s", mv->TMinFlt_max, RRDF_FIELD_SORT_DESCENDING,
443 NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
444 RRDF_FIELD_OPTS_NONE, NULL);
445 buffer_rrdf_table_add_field(wb, field_id++, "TMajFlt", "Total Major Page Faults/s",
446 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
447 RRDF_FIELD_TRANSFORM_NUMBER, 2, "pgflts/s", mv->TMajFlt_max, RRDF_FIELD_SORT_DESCENDING,
448 NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
449 RRDF_FIELD_OPTS_NONE, NULL);
450 #endif
451
452 #if (PROCESSES_HAVE_FDS == 1)
453 // open file descriptors
454 #if (PROCESSES_HAVE_PID_LIMITS == 1)
455 buffer_rrdf_table_add_field(wb, field_id++, "FDsLimitPercent", "Percentage of Open Descriptors vs Limits",
456 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
457 RRDF_FIELD_TRANSFORM_NUMBER, 2, "%", mv->FDsLimitPercent_max, RRDF_FIELD_SORT_DESCENDING, NULL,
458 RRDF_FIELD_SUMMARY_MAX, RRDF_FIELD_FILTER_RANGE,
459 RRDF_FIELD_OPTS_NONE, NULL);
460 #endif
461 buffer_rrdf_table_add_field(wb, field_id++, "FDs", "All Open File Descriptors",
462 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
463 RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", mv->FDs_max, RRDF_FIELD_SORT_DESCENDING, NULL,
464 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
465 RRDF_FIELD_OPTS_NONE, NULL);
466
467 buffer_rrdf_table_add_field(wb, field_id++, "Files", "Open Files", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
468 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
469 "fds",
470 mv->Files_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
471 RRDF_FIELD_FILTER_RANGE,
472 RRDF_FIELD_OPTS_NONE, NULL);
473 buffer_rrdf_table_add_field(wb, field_id++, "Pipes", "Open Pipes", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
474 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
475 "fds",
476 mv->Pipes_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
477 RRDF_FIELD_FILTER_RANGE,
478 RRDF_FIELD_OPTS_NONE, NULL);
479 buffer_rrdf_table_add_field(wb, field_id++, "Sockets", "Open Sockets", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
480 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
481 "fds", mv->Sockets_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
482 RRDF_FIELD_FILTER_RANGE,
483 RRDF_FIELD_OPTS_NONE, NULL);
484 buffer_rrdf_table_add_field(wb, field_id++, "iNotiFDs", "Open iNotify Descriptors",
485 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
486 RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", mv->iNotiFDs_max, RRDF_FIELD_SORT_DESCENDING,
487 NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
488 RRDF_FIELD_OPTS_NONE, NULL);
489 buffer_rrdf_table_add_field(wb, field_id++, "EventFDs", "Open Event Descriptors",
490 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
491 RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", mv->EventFDs_max, RRDF_FIELD_SORT_DESCENDING,
492 NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
493 RRDF_FIELD_OPTS_NONE, NULL);
494 buffer_rrdf_table_add_field(wb, field_id++, "TimerFDs", "Open Timer Descriptors",
495 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
496 RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", mv->TimerFDs_max, RRDF_FIELD_SORT_DESCENDING,
497 NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
498 RRDF_FIELD_OPTS_NONE, NULL);
499 buffer_rrdf_table_add_field(wb, field_id++, "SigFDs", "Open Signal Descriptors",
500 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
501 RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", mv->SigFDs_max, RRDF_FIELD_SORT_DESCENDING, NULL,
502 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
503 RRDF_FIELD_OPTS_NONE, NULL);
504 buffer_rrdf_table_add_field(wb, field_id++, "EvPollFDs", "Open Event Poll Descriptors",
505 RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
506 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", mv->EvPollFDs_max,
507 RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
508 RRDF_FIELD_OPTS_NONE, NULL);
509 buffer_rrdf_table_add_field(wb, field_id++, "OtherFDs", "Other Open Descriptors",
510 RRDF_FIELD_TYPE_BAR_WITH_INTEGER, RRDF_FIELD_VISUAL_BAR,
511 RRDF_FIELD_TRANSFORM_NUMBER, 0, "fds", mv->OtherFDs_max, RRDF_FIELD_SORT_DESCENDING,
512 NULL, RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
513 RRDF_FIELD_OPTS_NONE, NULL);
514 #endif
515
516 #if (PROCESSES_HAVE_HANDLES == 1)
517 buffer_rrdf_table_add_field(wb, field_id++, "Handles", "Open Handles", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
518 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
519 "handles",
520 mv->Handles_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
521 RRDF_FIELD_FILTER_RANGE,
522 RRDF_FIELD_OPTS_VISIBLE, NULL);
523 #endif
524
525 // processes, threads, uptime
526 buffer_rrdf_table_add_field(wb, field_id++, "Processes", "Processes", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
527 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
528 "processes", mv->Processes_max, RRDF_FIELD_SORT_DESCENDING, NULL,
529 RRDF_FIELD_SUMMARY_SUM, RRDF_FIELD_FILTER_RANGE,
530 RRDF_FIELD_OPTS_NONE, NULL);
531 buffer_rrdf_table_add_field(wb, field_id++, "Threads", "Threads", RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
532 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_NUMBER, 0,
533 "threads", mv->Threads_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_SUM,
534 RRDF_FIELD_FILTER_RANGE,
535 RRDF_FIELD_OPTS_NONE, NULL);
536 buffer_rrdf_table_add_field(wb, field_id++, "Uptime", "Uptime in seconds", RRDF_FIELD_TYPE_DURATION,
537 RRDF_FIELD_VISUAL_BAR, RRDF_FIELD_TRANSFORM_DURATION_S, 2,
538 "seconds", mv->Uptime_max, RRDF_FIELD_SORT_DESCENDING, NULL, RRDF_FIELD_SUMMARY_MAX,
539 RRDF_FIELD_FILTER_RANGE,
540 RRDF_FIELD_OPTS_VISIBLE, NULL);
541 }
542 buffer_json_object_close(wb); // columns
543 }
544
545 static void fp_emit_charts(BUFFER *wb, uint64_t total_memory_bytes) {
546 buffer_json_member_add_object(wb, "charts");
547 {
548 // CPU chart
549 buffer_json_member_add_object(wb, "CPU");
550 {
551 buffer_json_member_add_string(wb, "name", "CPU Utilization");
552 buffer_json_member_add_string(wb, "type", "stacked-bar");
553 buffer_json_member_add_array(wb, "columns");
554 {
555 buffer_json_add_array_item_string(wb, "UserCPU");
556 buffer_json_add_array_item_string(wb, "SysCPU");
557 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
558 buffer_json_add_array_item_string(wb, "GuestCPU");
559 #endif
560 #if (PROCESSES_HAVE_CPU_CHILDREN_TIME == 1)
561 buffer_json_add_array_item_string(wb, "CUserCPU");
562 buffer_json_add_array_item_string(wb, "CSysCPU");
563 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
564 buffer_json_add_array_item_string(wb, "CGuestCPU");
565 #endif
566 #endif
567 }
568 buffer_json_array_close(wb);
569 }
570 buffer_json_object_close(wb);
571
572 #if (PROCESSES_HAVE_VOLCTX == 1) || (PROCESSES_HAVE_NVOLCTX == 1)
573 buffer_json_member_add_object(wb, "CPUCtxSwitches");
574 {
575 buffer_json_member_add_string(wb, "name", "CPU Context Switches");
576 buffer_json_member_add_string(wb, "type", "stacked-bar");
577 buffer_json_member_add_array(wb, "columns");
578 {
579 #if (PROCESSES_HAVE_VOLCTX == 1)
580 buffer_json_add_array_item_string(wb, "vCtxSwitch");
581 #endif
582 #if (PROCESSES_HAVE_NVOLCTX == 1)
583 buffer_json_add_array_item_string(wb, "iCtxSwitch");
584 #endif
585 }
586 buffer_json_array_close(wb);
587 }
588 buffer_json_object_close(wb);
589 #endif
590
591 // Memory chart
592 buffer_json_member_add_object(wb, "Memory");
593 {
594 buffer_json_member_add_string(wb, "name", "Memory");
595 buffer_json_member_add_string(wb, "type", "stacked-bar");
596 buffer_json_member_add_array(wb, "columns");
597 {
598 buffer_json_add_array_item_string(wb, "Virtual");
599 buffer_json_add_array_item_string(wb, "Resident");
600 buffer_json_add_array_item_string(wb, "Shared");
601 buffer_json_add_array_item_string(wb, "Swap");
602 }
603 buffer_json_array_close(wb);
604 }
605 buffer_json_object_close(wb);
606
607 if(total_memory_bytes) {
608 buffer_json_member_add_object(wb, "MemoryPercent");
609 {
610 buffer_json_member_add_string(wb, "name", "Memory Percentage");
611 buffer_json_member_add_string(wb, "type", "stacked-bar");
612 buffer_json_member_add_array(wb, "columns");
613 {
614 buffer_json_add_array_item_string(wb, "Memory");
615 }
616 buffer_json_array_close(wb);
617 }
618 buffer_json_object_close(wb);
619 }
620
621 #if (PROCESSES_HAVE_LOGICAL_IO == 1) || (PROCESSES_HAVE_PHYSICAL_IO == 1)
622 // I/O Reads chart
623 buffer_json_member_add_object(wb, "Reads");
624 {
625 buffer_json_member_add_string(wb, "name", "I/O Reads");
626 buffer_json_member_add_string(wb, "type", "stacked-bar");
627 buffer_json_member_add_array(wb, "columns");
628 {
629 #if (PROCESSES_HAVE_LOGICAL_IO == 1)
630 buffer_json_add_array_item_string(wb, "LReads");
631 #endif
632 #if (PROCESSES_HAVE_PHYSICAL_IO == 1)
633 buffer_json_add_array_item_string(wb, "PReads");
634 #endif
635 }
636 buffer_json_array_close(wb);
637 }
638 buffer_json_object_close(wb);
639
640 // I/O Writes chart
641 buffer_json_member_add_object(wb, "Writes");
642 {
643 buffer_json_member_add_string(wb, "name", "I/O Writes");
644 buffer_json_member_add_string(wb, "type", "stacked-bar");
645 buffer_json_member_add_array(wb, "columns");
646 {
647 #if (PROCESSES_HAVE_LOGICAL_IO == 1)
648 buffer_json_add_array_item_string(wb, "LWrites");
649 #endif
650 #if (PROCESSES_HAVE_PHYSICAL_IO == 1)
651 buffer_json_add_array_item_string(wb, "PWrites");
652 #endif
653 }
654 buffer_json_array_close(wb);
655 }
656 buffer_json_object_close(wb);
657 #endif
658
659 #if (PROCESSES_HAVE_LOGICAL_IO == 1)
660 // Logical I/O chart
661 buffer_json_member_add_object(wb, "LogicalIO");
662 {
663 buffer_json_member_add_string(wb, "name", "Logical I/O");
664 buffer_json_member_add_string(wb, "type", "stacked-bar");
665 buffer_json_member_add_array(wb, "columns");
666 {
667 buffer_json_add_array_item_string(wb, "LReads");
668 buffer_json_add_array_item_string(wb, "LWrites");
669 }
670 buffer_json_array_close(wb);
671 }
672 buffer_json_object_close(wb);
673 #endif
674
675 #if (PROCESSES_HAVE_PHYSICAL_IO == 1)
676 // Physical I/O chart
677 buffer_json_member_add_object(wb, "PhysicalIO");
678 {
679 buffer_json_member_add_string(wb, "name", "Physical I/O");
680 buffer_json_member_add_string(wb, "type", "stacked-bar");
681 buffer_json_member_add_array(wb, "columns");
682 {
683 buffer_json_add_array_item_string(wb, "PReads");
684 buffer_json_add_array_item_string(wb, "PWrites");
685 }
686 buffer_json_array_close(wb);
687 }
688 buffer_json_object_close(wb);
689 #endif
690
691 #if (PROCESSES_HAVE_IO_CALLS == 1)
692 // I/O Calls chart
693 buffer_json_member_add_object(wb, "IOCalls");
694 {
695 buffer_json_member_add_string(wb, "name", "I/O Calls");
696 buffer_json_member_add_string(wb, "type", "stacked-bar");
697 buffer_json_member_add_array(wb, "columns");
698 {
699 buffer_json_add_array_item_string(wb, "ROps");
700 buffer_json_add_array_item_string(wb, "WOps");
701 }
702 buffer_json_array_close(wb);
703 }
704 buffer_json_object_close(wb);
705 #endif
706
707 // Minor Page Faults chart
708 buffer_json_member_add_object(wb, "MinFlt");
709 {
710 buffer_json_member_add_string(wb, "name", "Minor Page Faults");
711 buffer_json_member_add_string(wb, "type", "stacked-bar");
712 buffer_json_member_add_array(wb, "columns");
713 {
714 buffer_json_add_array_item_string(wb, "MinFlt");
715 buffer_json_add_array_item_string(wb, "CMinFlt");
716 }
717 buffer_json_array_close(wb);
718 }
719 buffer_json_object_close(wb);
720
721 // Major Page Faults chart
722 buffer_json_member_add_object(wb, "MajFlt");
723 {
724 buffer_json_member_add_string(wb, "name", "Major Page Faults");
725 buffer_json_member_add_string(wb, "type", "stacked-bar");
726 buffer_json_member_add_array(wb, "columns");
727 {
728 buffer_json_add_array_item_string(wb, "MajFlt");
729 buffer_json_add_array_item_string(wb, "CMajFlt");
730 }
731 buffer_json_array_close(wb);
732 }
733 buffer_json_object_close(wb);
734
735 // Threads chart
736 buffer_json_member_add_object(wb, "Threads");
737 {
738 buffer_json_member_add_string(wb, "name", "Threads");
739 buffer_json_member_add_string(wb, "type", "stacked-bar");
740 buffer_json_member_add_array(wb, "columns");
741 {
742 buffer_json_add_array_item_string(wb, "Threads");
743 }
744 buffer_json_array_close(wb);
745 }
746 buffer_json_object_close(wb);
747
748 // Processes chart
749 buffer_json_member_add_object(wb, "Processes");
750 {
751 buffer_json_member_add_string(wb, "name", "Processes");
752 buffer_json_member_add_string(wb, "type", "stacked-bar");
753 buffer_json_member_add_array(wb, "columns");
754 {
755 buffer_json_add_array_item_string(wb, "Processes");
756 }
757 buffer_json_array_close(wb);
758 }
759 buffer_json_object_close(wb);
760
761 #if (PROCESSES_HAVE_FDS == 1)
762 // FDs chart
763 buffer_json_member_add_object(wb, "FDs");
764 {
765 buffer_json_member_add_string(wb, "name", "File Descriptors");
766 buffer_json_member_add_string(wb, "type", "stacked-bar");
767 buffer_json_member_add_array(wb, "columns");
768 {
769 buffer_json_add_array_item_string(wb, "Files");
770 buffer_json_add_array_item_string(wb, "Pipes");
771 buffer_json_add_array_item_string(wb, "Sockets");
772 buffer_json_add_array_item_string(wb, "iNotiFDs");
773 buffer_json_add_array_item_string(wb, "EventFDs");
774 buffer_json_add_array_item_string(wb, "TimerFDs");
775 buffer_json_add_array_item_string(wb, "SigFDs");
776 buffer_json_add_array_item_string(wb, "EvPollFDs");
777 buffer_json_add_array_item_string(wb, "OtherFDs");
778 }
779 buffer_json_array_close(wb);
780 }
781 buffer_json_object_close(wb);
782 #endif
783
784 #if (PROCESSES_HAVE_HANDLES == 1)
785 // Handles chart
786 buffer_json_member_add_object(wb, "Handles");
787 {
788 buffer_json_member_add_string(wb, "name", "Handles");
789 buffer_json_member_add_string(wb, "type", "stacked-bar");
790 buffer_json_member_add_array(wb, "columns");
791 {
792 buffer_json_add_array_item_string(wb, "Handles");
793 }
794 buffer_json_array_close(wb);
795 }
796 buffer_json_object_close(wb);
797 #endif
798 }
799 buffer_json_object_close(wb); // charts
800 }
801
802 static void fp_emit_groupby(BUFFER *wb) {
803 buffer_json_member_add_array(wb, "default_charts");
804 {
805 buffer_json_add_array_item_array(wb);
806 buffer_json_add_array_item_string(wb, "CPU");
807 buffer_json_add_array_item_string(wb, "Category");
808 buffer_json_array_close(wb);
809
810 buffer_json_add_array_item_array(wb);
811 buffer_json_add_array_item_string(wb, "Memory");
812 buffer_json_add_array_item_string(wb, "Category");
813 buffer_json_array_close(wb);
814 }
815 buffer_json_array_close(wb);
816
817 buffer_json_member_add_object(wb, "group_by");
818 {
819 // group by PID
820 buffer_json_member_add_object(wb, "PID");
821 {
822 buffer_json_member_add_string(wb, "name", "Process Tree by PID");
823 buffer_json_member_add_array(wb, "columns");
824 {
825 buffer_json_add_array_item_string(wb, "PPID");
826 }
827 buffer_json_array_close(wb);
828 }
829 buffer_json_object_close(wb);
830
831 // group by Category
832 buffer_json_member_add_object(wb, "Category");
833 {
834 buffer_json_member_add_string(wb, "name", "Process Tree by Category");
835 buffer_json_member_add_array(wb, "columns");
836 {
837 buffer_json_add_array_item_string(wb, "Category");
838 buffer_json_add_array_item_string(wb, "PPID");
839 }
840 buffer_json_array_close(wb);
841 }
842 buffer_json_object_close(wb);
843
844 // group by PPID
845 buffer_json_member_add_object(wb, "PPID");
846 {
847 buffer_json_member_add_string(wb, "name", "Process Tree by Parent PID");
848 buffer_json_member_add_array(wb, "columns");
849 {
850 buffer_json_add_array_item_string(wb, "PPID");
851 buffer_json_add_array_item_string(wb, "PID");
852 }
853 buffer_json_array_close(wb);
854 }
855 buffer_json_object_close(wb);
856
857 #if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
858 // group by User
859 buffer_json_member_add_object(wb, "User");
860 {
861 buffer_json_member_add_string(wb, "name", "Process Tree by User");
862 buffer_json_member_add_array(wb, "columns");
863 {
864 buffer_json_add_array_item_string(wb, "User");
865 buffer_json_add_array_item_string(wb, "PPID");
866 }
867 buffer_json_array_close(wb);
868 }
869 buffer_json_object_close(wb);
870 #endif
871
872 #if (PROCESSES_HAVE_GID == 1)
873 // group by Group
874 buffer_json_member_add_object(wb, "Group");
875 {
876 buffer_json_member_add_string(wb, "name", "Process Tree by Group");
877 buffer_json_member_add_array(wb, "columns");
878 {
879 buffer_json_add_array_item_string(wb, "Group");
880 buffer_json_add_array_item_string(wb, "PPID");
881 }
882 buffer_json_array_close(wb);
883 }
884 buffer_json_object_close(wb);
885 #endif
886 }
887 buffer_json_object_close(wb); // group_by
888 }
889
890 void function_processes(const char *transaction, char *function,
891 usec_t *stop_monotonic_ut __maybe_unused, bool *cancelled __maybe_unused,
892 BUFFER *payload __maybe_unused, HTTP_ACCESS access,
893 const char *source __maybe_unused, void *data __maybe_unused) {
894 time_t now_s = now_realtime_sec();
895 struct pid_stat *p;
896
897 bool show_cmdline = http_access_user_has_enough_access_level_for_endpoint(
898 access, HTTP_ACCESS_SIGNED_ID | HTTP_ACCESS_SAME_SPACE | HTTP_ACCESS_SENSITIVE_DATA | HTTP_ACCESS_VIEW_AGENT_CONFIG) || enable_function_cmdline;
899
900 char *words[PLUGINSD_MAX_WORDS] = { NULL };
901 size_t num_words = quoted_strings_splitter_whitespace(function, words, PLUGINSD_MAX_WORDS);
902
903 struct target *category = NULL, *user = NULL, *group = NULL; (void)category; (void)user; (void)group;
904 #if (PROCESSES_HAVE_UID == 1)
905 struct target *users_sid_root = users_root_target;
906 #endif
907 #if (PROCESSES_HAVE_SID == 1)
908 struct target *users_sid_root = sids_root_target;
909 #endif
910 const char *process_name = NULL;
911 pid_t pid = 0;
912 uid_t uid = 0; (void)uid;
913 gid_t gid = 0; (void)gid;
914 bool info = false;
915
916 bool filter_pid = false, filter_uid = false, filter_gid = false;
917 (void)filter_uid; (void)filter_gid;
918
919 for(int i = 1; i < PLUGINSD_MAX_WORDS ;i++) {
920 const char *keyword = get_word(words, num_words, i);
921 if(!keyword) break;
922
923 if(!category && strncmp(keyword, PROCESS_FILTER_CATEGORY, strlen(PROCESS_FILTER_CATEGORY)) == 0) {
924 category = find_target_by_name(apps_groups_root_target, &keyword[strlen(PROCESS_FILTER_CATEGORY)]);
925 if(!category) {
926 pluginsd_function_json_error_to_stdout(transaction, HTTP_RESP_BAD_REQUEST,
927 "No category with that name found.");
928 return;
929 }
930 }
931 #if (PROCESSES_HAVE_UID == 1) || (PROCESSES_HAVE_SID == 1)
932 else if(!user && strncmp(keyword, PROCESS_FILTER_USER, strlen(PROCESS_FILTER_USER)) == 0) {
933 user = find_target_by_name(users_sid_root, &keyword[strlen(PROCESS_FILTER_USER)]);
934 if(!user) {
935 pluginsd_function_json_error_to_stdout(transaction, HTTP_RESP_BAD_REQUEST,
936 "No user with that name found.");
937 return;
938 }
939 }
940 #endif
941 #if (PROCESSES_HAVE_GID == 1)
942 else if(strncmp(keyword, PROCESS_FILTER_GROUP, strlen(PROCESS_FILTER_GROUP)) == 0) {
943 group = find_target_by_name(groups_root_target, &keyword[strlen(PROCESS_FILTER_GROUP)]);
944 if(!group) {
945 pluginsd_function_json_error_to_stdout(transaction, HTTP_RESP_BAD_REQUEST,
946 "No group with that name found.");
947 return;
948 }
949 }
950 #endif
951 else if(!process_name && strncmp(keyword, PROCESS_FILTER_PROCESS, strlen(PROCESS_FILTER_PROCESS)) == 0) {
952 process_name = &keyword[strlen(PROCESS_FILTER_PROCESS)];
953 }
954 else if(!pid && strncmp(keyword, PROCESS_FILTER_PID, strlen(PROCESS_FILTER_PID)) == 0) {
955 pid = str2i(&keyword[strlen(PROCESS_FILTER_PID)]);
956 filter_pid = true;
957 }
958 #if (PROCESSES_HAVE_UID == 1)
959 else if(!uid && strncmp(keyword, PROCESS_FILTER_UID, strlen(PROCESS_FILTER_UID)) == 0) {
960 uid = str2i(&keyword[strlen(PROCESS_FILTER_UID)]);
961 filter_uid = true;
962 }
963 #endif
964 #if (PROCESSES_HAVE_GID == 1)
965 else if(!gid && strncmp(keyword, PROCESS_FILTER_GID, strlen(PROCESS_FILTER_GID)) == 0) {
966 gid = str2i(&keyword[strlen(PROCESS_FILTER_GID)]);
967 filter_gid = true;
968 }
969 #endif
970 else if(strcmp(keyword, "help") == 0) {
971 apps_plugin_function_processes_help(transaction);
972 return;
973 }
974 else if(strcmp(keyword, "info") == 0) {
975 info = true;
976 }
977 }
978
979 BUFFER *wb = buffer_create(4096, NULL);
980 buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_MINIFY);
981 buffer_json_member_add_uint64(wb, "status", HTTP_RESP_OK);
982 buffer_json_member_add_string(wb, "type", "table");
983 buffer_json_member_add_time_t(wb, "update_every", update_every);
984 buffer_json_member_add_boolean(wb, "has_history", false);
985 buffer_json_member_add_string(wb, "help", APPS_PLUGIN_PROCESSES_FUNCTION_DESCRIPTION);
986
987 if(info)
988 goto close_and_send;
989
990 buffer_json_member_add_array(wb, "data");
991
992 uint64_t cpu_divisor = NSEC_PER_SEC / 100;
993 unsigned int memory_divisor = 1024 * 1024;
994 unsigned int io_divisor = 1024 * RATES_DETAIL;
995
996 uint64_t total_memory_bytes = OS_FUNCTION(apps_os_get_total_memory)();
997
998 NETDATA_DOUBLE
999 UserCPU_max = 0.0
1000 , SysCPU_max = 0.0
1001 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
1002 , GuestCPU_max = 0.0
1003 #endif
1004 #if (PROCESSES_HAVE_CPU_CHILDREN_TIME == 1)
1005 , CUserCPU_max = 0.0
1006 , CSysCPU_max = 0.0
1007 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
1008 , CGuestCPU_max = 0.0
1009 #endif
1010 #endif
1011 , CPU_max = 0.0
1012 , VMSize_max = 0.0
1013 , RSS_max = 0.0
1014 #if (PROCESSES_HAVE_SMAPS_ROLLUP == 1)
1015 , Estimated_max = 0.0
1016 , Pss_max = 0.0
1017 , PssAge_max = 0.0
1018 , SharedRatio_max = 0.0
1019 #endif
1020 #if (PROCESSES_HAVE_VMSHARED == 1)
1021 , Shared_max = 0.0
1022 #endif
1023 , Swap_max = 0.0
1024 , Memory_max = 0.0
1025 #if (PROCESSES_HAVE_FDS == 1) && (PROCESSES_HAVE_PID_LIMITS == 1)
1026 , FDsLimitPercent_max = 0.0
1027 #endif
1028 ;
1029
1030 unsigned long long
1031 Processes_max = 0
1032 , Threads_max = 0
1033 #if (PROCESSES_HAVE_VOLCTX == 1)
1034 , VoluntaryCtxtSwitches_max = 0
1035 #endif
1036 #if (PROCESSES_HAVE_NVOLCTX == 1)
1037 , NonVoluntaryCtxtSwitches_max = 0
1038 #endif
1039 , Uptime_max = 0
1040 , MinFlt_max = 0
1041 #if (PROCESSES_HAVE_MAJFLT == 1)
1042 , MajFlt_max = 0
1043 #endif
1044 #if (PROCESSES_HAVE_CHILDREN_FLTS == 1)
1045 , CMinFlt_max = 0
1046 , CMajFlt_max = 0
1047 , TMinFlt_max = 0
1048 , TMajFlt_max = 0
1049 #endif
1050 #if (PROCESSES_HAVE_LOGICAL_IO == 1)
1051 , LReads_max = 0
1052 , LWrites_max = 0
1053 #endif
1054 #if (PROCESSES_HAVE_PHYSICAL_IO == 1)
1055 , PReads_max = 0
1056 , PWrites_max = 0
1057 #endif
1058 #if (PROCESSES_HAVE_IO_CALLS == 1)
1059 , ROps_max = 0
1060 , WOps_max = 0
1061 #endif
1062 #if (PROCESSES_HAVE_FDS == 1)
1063 , Files_max = 0
1064 , Pipes_max = 0
1065 , Sockets_max = 0
1066 , iNotiFDs_max = 0
1067 , EventFDs_max = 0
1068 , TimerFDs_max = 0
1069 , SigFDs_max = 0
1070 , EvPollFDs_max = 0
1071 , OtherFDs_max = 0
1072 , FDs_max = 0
1073 #endif
1074 #if (PROCESSES_HAVE_HANDLES == 1)
1075 , Handles_max = 0
1076 #endif
1077 ;
1078
1079 netdata_mutex_lock(&apps_and_stdout_mutex);
1080
1081 int rows= 0;
1082 for(p = root_of_pids(); p ; p = p->next) {
1083 if(!p->updated)
1084 continue;
1085
1086 if(category && p->target != category)
1087 continue;
1088
1089 #if (PROCESSES_HAVE_UID == 1)
1090 if(user && p->uid_target != user)
1091 continue;
1092 #endif
1093
1094 #if (PROCESSES_HAVE_GID == 1)
1095 if(group && p->gid_target != group)
1096 continue;
1097 #endif
1098
1099 #if (PROCESSES_HAVE_SID == 1)
1100 if(user && p->sid_target != user)
1101 continue;
1102 #endif
1103
1104 if(process_name && ((strcmp(pid_stat_comm(p), process_name) != 0 && !p->parent) || (p->parent && strcmp(pid_stat_comm(p), process_name) != 0 && strcmp(pid_stat_comm(p->parent), process_name) != 0)))
1105 continue;
1106
1107 if(filter_pid && p->pid != pid && p->ppid != pid)
1108 continue;
1109
1110 #if (PROCESSES_HAVE_UID == 1)
1111 if(filter_uid && p->uid != uid)
1112 continue;
1113 #endif
1114
1115 #if (PROCESSES_HAVE_GID == 1)
1116 if(filter_gid && p->gid != gid)
1117 continue;
1118 #endif
1119
1120 rows++;
1121
1122 buffer_json_add_array_item_array(wb); // for each pid
1123
1124 // IMPORTANT!
1125 // THE ORDER SHOULD BE THE SAME WITH THE FIELDS!
1126
1127 // pid
1128 buffer_json_add_array_item_uint64(wb, p->pid);
1129
1130 // cmd
1131 buffer_json_add_array_item_string(wb, string2str(p->comm));
1132
1133 #if (PROCESSES_HAVE_COMM_AND_NAME == 1)
1134 // name
1135 buffer_json_add_array_item_string(wb, string2str(p->name ? p->name : p->comm));
1136 #endif
1137
1138 // cmdline
1139 if (show_cmdline) {
1140 buffer_json_add_array_item_string(wb, (string_strlen(p->cmdline)) ? pid_stat_cmdline(p) : pid_stat_comm(p));
1141 }
1142
1143 // ppid
1144 buffer_json_add_array_item_uint64(wb, p->ppid);
1145
1146 // category
1147 buffer_json_add_array_item_string(wb, p->target ? string2str(p->target->name) : "-");
1148
1149 #if (PROCESSES_HAVE_UID == 1)
1150 // user
1151 buffer_json_add_array_item_string(wb, p->uid_target ? string2str(p->uid_target->name) : "-");
1152
1153 // uid
1154 buffer_json_add_array_item_uint64(wb, p->uid);
1155 #endif
1156 #if (PROCESSES_HAVE_SID == 1)
1157 // account
1158 buffer_json_add_array_item_string(wb, p->sid_target ? string2str(p->sid_target->name) : "-");
1159 #endif
1160
1161 #if (PROCESSES_HAVE_GID == 1)
1162 // group
1163 buffer_json_add_array_item_string(wb, p->gid_target ? string2str(p->gid_target->name) : "-");
1164
1165 // gid
1166 buffer_json_add_array_item_uint64(wb, p->gid);
1167 #endif
1168
1169 // CPU utilization %
1170 kernel_uint_t total_cpu = p->values[PDF_UTIME] + p->values[PDF_STIME];
1171
1172 #if (PROCESSES_HAVE_CPU_GUEST_TIME)
1173 total_cpu += p->values[PDF_GTIME];
1174 #endif
1175 #if (PROCESSES_HAVE_CPU_CHILDREN_TIME)
1176 total_cpu += p->values[PDF_CUTIME] + p->values[PDF_CSTIME];
1177 #if (PROCESSES_HAVE_CPU_GUEST_TIME)
1178 total_cpu += p->values[PDF_CGTIME];
1179 #endif
1180 #endif
1181 add_value_field_ndd_with_max(wb, CPU, (NETDATA_DOUBLE)(total_cpu) / cpu_divisor);
1182
1183 add_value_field_ndd_with_max(wb, UserCPU, (NETDATA_DOUBLE)(p->values[PDF_UTIME]) / cpu_divisor);
1184 add_value_field_ndd_with_max(wb, SysCPU, (NETDATA_DOUBLE)(p->values[PDF_STIME]) / cpu_divisor);
1185 #if (PROCESSES_HAVE_CPU_GUEST_TIME)
1186 add_value_field_ndd_with_max(wb, GuestCPU, (NETDATA_DOUBLE)(p->values[PDF_GTIME]) / cpu_divisor);
1187 #endif
1188 #if (PROCESSES_HAVE_CPU_CHILDREN_TIME)
1189 add_value_field_ndd_with_max(wb, CUserCPU, (NETDATA_DOUBLE)(p->values[PDF_CUTIME]) / cpu_divisor);
1190 add_value_field_ndd_with_max(wb, CSysCPU, (NETDATA_DOUBLE)(p->values[PDF_CSTIME]) / cpu_divisor);
1191 #if (PROCESSES_HAVE_CPU_GUEST_TIME)
1192 add_value_field_ndd_with_max(wb, CGuestCPU, (NETDATA_DOUBLE)(p->values[PDF_CGTIME]) / cpu_divisor);
1193 #endif
1194 #endif
1195
1196 #if (PROCESSES_HAVE_VOLCTX == 1)
1197 add_value_field_llu_with_max(wb, VoluntaryCtxtSwitches, p->values[PDF_VOLCTX] / RATES_DETAIL);
1198 #endif
1199 #if (PROCESSES_HAVE_NVOLCTX == 1)
1200 add_value_field_llu_with_max(wb, NonVoluntaryCtxtSwitches, p->values[PDF_NVOLCTX] / RATES_DETAIL);
1201 #endif
1202
1203 // memory MiB
1204 if(total_memory_bytes)
1205 add_value_field_ndd_with_max(wb, Memory, (NETDATA_DOUBLE)p->values[PDF_VMRSS] * 100.0 / (NETDATA_DOUBLE)total_memory_bytes);
1206
1207 add_value_field_ndd_with_max(wb, RSS, (NETDATA_DOUBLE)p->values[PDF_VMRSS] / memory_divisor);
1208 #if (PROCESSES_HAVE_SMAPS_ROLLUP == 1)
1209 if(pss_refresh_period > 0) {
1210 add_value_field_ndd_with_max(wb, Estimated, (NETDATA_DOUBLE)p->values[PDF_MEM_ESTIMATED] / memory_divisor);
1211 add_value_field_ndd_with_max(wb, Pss, (NETDATA_DOUBLE)p->values[PDF_PSS] / memory_divisor);
1212 NETDATA_DOUBLE pss_age;
1213 if(p->last_pss_iteration == 0)
1214 pss_age = NAN;
1215 else if(global_iterations_counter >= p->last_pss_iteration)
1216 pss_age = (NETDATA_DOUBLE)(global_iterations_counter - p->last_pss_iteration) * update_every;
1217 else
1218 pss_age = NAN;
1219 add_value_field_ndd_with_max(wb, PssAge, pss_age);
1220 NETDATA_DOUBLE shared_ratio = p->pss_total_ratio * 100.0;
1221 add_value_field_ndd_with_max(wb, SharedRatio, shared_ratio);
1222 }
1223 #endif
1224 #if (PROCESSES_HAVE_VMSHARED == 1)
1225 add_value_field_ndd_with_max(wb, Shared, (NETDATA_DOUBLE)p->values[PDF_VMSHARED] / memory_divisor);
1226 #endif
1227
1228 add_value_field_ndd_with_max(wb, VMSize, (NETDATA_DOUBLE)p->values[PDF_VMSIZE] / memory_divisor);
1229
1230 #if (PROCESSES_HAVE_VMSWAP == 1)
1231 add_value_field_ndd_with_max(wb, Swap, (NETDATA_DOUBLE)p->values[PDF_VMSWAP] / memory_divisor);
1232 #endif
1233
1234 #if (PROCESSES_HAVE_PHYSICAL_IO == 1)
1235 // Physical I/O
1236 add_value_field_llu_with_max(wb, PReads, p->values[PDF_PREAD] / io_divisor);
1237 add_value_field_llu_with_max(wb, PWrites, p->values[PDF_PWRITE] / io_divisor);
1238 #endif
1239
1240 #if (PROCESSES_HAVE_LOGICAL_IO == 1)
1241 // Logical I/O
1242 add_value_field_llu_with_max(wb, LReads, p->values[PDF_LREAD] / io_divisor);
1243 add_value_field_llu_with_max(wb, LWrites, p->values[PDF_LWRITE] / io_divisor);
1244 #endif
1245
1246 #if (PROCESSES_HAVE_IO_CALLS == 1)
1247 // I/O calls
1248 add_value_field_llu_with_max(wb, ROps, p->values[PDF_OREAD] / RATES_DETAIL);
1249 add_value_field_llu_with_max(wb, WOps, p->values[PDF_OWRITE] / RATES_DETAIL);
1250 #endif
1251
1252 // minor page faults
1253 add_value_field_llu_with_max(wb, MinFlt, p->values[PDF_MINFLT] / RATES_DETAIL);
1254
1255 #if (PROCESSES_HAVE_MAJFLT == 1)
1256 // major page faults
1257 add_value_field_llu_with_max(wb, MajFlt, p->values[PDF_MAJFLT] / RATES_DETAIL);
1258 #endif
1259
1260 #if (PROCESSES_HAVE_CHILDREN_FLTS == 1)
1261 add_value_field_llu_with_max(wb, CMinFlt, p->values[PDF_CMINFLT] / RATES_DETAIL);
1262 add_value_field_llu_with_max(wb, CMajFlt, p->values[PDF_CMAJFLT] / RATES_DETAIL);
1263 add_value_field_llu_with_max(wb, TMinFlt, (p->values[PDF_MINFLT] + p->values[PDF_CMINFLT]) / RATES_DETAIL);
1264 add_value_field_llu_with_max(wb, TMajFlt, (p->values[PDF_MAJFLT] + p->values[PDF_CMAJFLT]) / RATES_DETAIL);
1265 #endif
1266
1267 #if (PROCESSES_HAVE_FDS == 1)
1268 // open file descriptors
1269 #if (PROCESSES_HAVE_PID_LIMITS == 1)
1270 add_value_field_ndd_with_max(wb, FDsLimitPercent, p->openfds_limits_percent);
1271 #endif
1272 add_value_field_llu_with_max(wb, FDs, pid_openfds_sum(p));
1273
1274 add_value_field_llu_with_max(wb, Files, p->openfds.files);
1275 add_value_field_llu_with_max(wb, Pipes, p->openfds.pipes);
1276 add_value_field_llu_with_max(wb, Sockets, p->openfds.sockets);
1277 add_value_field_llu_with_max(wb, iNotiFDs, p->openfds.inotifies);
1278 add_value_field_llu_with_max(wb, EventFDs, p->openfds.eventfds);
1279 add_value_field_llu_with_max(wb, TimerFDs, p->openfds.timerfds);
1280 add_value_field_llu_with_max(wb, SigFDs, p->openfds.signalfds);
1281 add_value_field_llu_with_max(wb, EvPollFDs, p->openfds.eventpolls);
1282 add_value_field_llu_with_max(wb, OtherFDs, p->openfds.other);
1283 #endif
1284
1285 #if (PROCESSES_HAVE_HANDLES == 1)
1286 add_value_field_llu_with_max(wb, Handles, p->values[PDF_HANDLES]);
1287 #endif
1288
1289 // processes, threads, uptime
1290 add_value_field_llu_with_max(wb, Processes, p->values[PDF_PROCESSES]);
1291 add_value_field_llu_with_max(wb, Threads, p->values[PDF_THREADS]);
1292 add_value_field_llu_with_max(wb, Uptime, p->values[PDF_UPTIME]);
1293
1294 buffer_json_array_close(wb); // for each pid
1295 }
1296
1297 buffer_json_array_close(wb); // data
1298
1299 struct fp_maxvals mv = {
1300 .UserCPU_max = UserCPU_max,
1301 .SysCPU_max = SysCPU_max,
1302 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
1303 .GuestCPU_max = GuestCPU_max,
1304 #endif
1305 #if (PROCESSES_HAVE_CPU_CHILDREN_TIME == 1)
1306 .CUserCPU_max = CUserCPU_max,
1307 .CSysCPU_max = CSysCPU_max,
1308 #if (PROCESSES_HAVE_CPU_GUEST_TIME == 1)
1309 .CGuestCPU_max = CGuestCPU_max,
1310 #endif
1311 #endif
1312 .CPU_max = CPU_max,
1313 .VMSize_max = VMSize_max,
1314 .RSS_max = RSS_max,
1315 #if (PROCESSES_HAVE_SMAPS_ROLLUP == 1)
1316 .Estimated_max = Estimated_max,
1317 .Pss_max = Pss_max,
1318 .PssAge_max = PssAge_max,
1319 .SharedRatio_max = SharedRatio_max,
1320 #endif
1321 #if (PROCESSES_HAVE_VMSHARED == 1)
1322 .Shared_max = Shared_max,
1323 #endif
1324 .Swap_max = Swap_max,
1325 #if (PROCESSES_HAVE_FDS == 1) && (PROCESSES_HAVE_PID_LIMITS == 1)
1326 .FDsLimitPercent_max = FDsLimitPercent_max,
1327 #endif
1328 .Processes_max = Processes_max,
1329 .Threads_max = Threads_max,
1330 #if (PROCESSES_HAVE_VOLCTX == 1)
1331 .VoluntaryCtxtSwitches_max = VoluntaryCtxtSwitches_max,
1332 #endif
1333 #if (PROCESSES_HAVE_NVOLCTX == 1)
1334 .NonVoluntaryCtxtSwitches_max = NonVoluntaryCtxtSwitches_max,
1335 #endif
1336 .Uptime_max = Uptime_max,
1337 .MinFlt_max = MinFlt_max,
1338 #if (PROCESSES_HAVE_MAJFLT == 1)
1339 .MajFlt_max = MajFlt_max,
1340 #endif
1341 #if (PROCESSES_HAVE_CHILDREN_FLTS == 1)
1342 .CMinFlt_max = CMinFlt_max,
1343 .CMajFlt_max = CMajFlt_max,
1344 .TMinFlt_max = TMinFlt_max,
1345 .TMajFlt_max = TMajFlt_max,
1346 #endif
1347 #if (PROCESSES_HAVE_LOGICAL_IO == 1)
1348 .LReads_max = LReads_max,
1349 .LWrites_max = LWrites_max,
1350 #endif
1351 #if (PROCESSES_HAVE_PHYSICAL_IO == 1)
1352 .PReads_max = PReads_max,
1353 .PWrites_max = PWrites_max,
1354 #endif
1355 #if (PROCESSES_HAVE_IO_CALLS == 1)
1356 .ROps_max = ROps_max,
1357 .WOps_max = WOps_max,
1358 #endif
1359 #if (PROCESSES_HAVE_FDS == 1)
1360 .Files_max = Files_max,
1361 .Pipes_max = Pipes_max,
1362 .Sockets_max = Sockets_max,
1363 .iNotiFDs_max = iNotiFDs_max,
1364 .EventFDs_max = EventFDs_max,
1365 .TimerFDs_max = TimerFDs_max,
1366 .SigFDs_max = SigFDs_max,
1367 .EvPollFDs_max = EvPollFDs_max,
1368 .OtherFDs_max = OtherFDs_max,
1369 .FDs_max = FDs_max,
1370 #endif
1371 #if (PROCESSES_HAVE_HANDLES == 1)
1372 .Handles_max = Handles_max,
1373 #endif
1374 };
1375
1376 fp_emit_columns(wb, &mv, show_cmdline, total_memory_bytes);
1377
1378 buffer_json_member_add_string(wb, "default_sort_column", "CPU");
1379
1380 fp_emit_charts(wb, total_memory_bytes);
1381
1382 fp_emit_groupby(wb);
1383
1384 netdata_mutex_unlock(&apps_and_stdout_mutex);
1385
1386 close_and_send:
1387 buffer_json_member_add_time_t(wb, "expires", now_s + update_every);
1388 buffer_json_finalize(wb);
1389
1390 wb->response_code = HTTP_RESP_OK;
1391 wb->content_type = CT_APPLICATION_JSON;
1392 wb->expires = now_s + update_every;
1393 pluginsd_function_result_to_stdout(transaction, wb);
1394
1395 buffer_free(wb);
1396 }