Skip to content

Commit e5f647f

Browse files
committed
in_mem_metrics: make filters multi-value and non-exclusive.
Allow using comma delimited values for the PID, exec(utable) and cmdline filters to allow for multiple values. All these filters are non-exclusive so a process that matches any one of them is chosen to be polled for metrics. Signed-off-by: Phillip Whelan <[email protected]>
1 parent 5b6dd68 commit e5f647f

File tree

1 file changed

+139
-45
lines changed

1 file changed

+139
-45
lines changed

plugins/in_mem_metrics/mem_metrics.c

Lines changed: 139 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ struct mem_metrics {
3939
int coll_fd;
4040
struct flb_input_instance *ins;
4141
flb_sds_t procfs_path;
42-
flb_sds_t chosen_cmd;
43-
flb_sds_t chosen_exec;
44-
pid_t chosen_pid;
42+
struct mk_list *chosen_cmd;
43+
struct mk_list *chosen_exec;
44+
struct mk_list *chosen_pid;
4545

4646
int interval_sec;
4747
int interval_nsec;
@@ -66,64 +66,158 @@ struct mem_metrics {
6666
struct cmt_gauge *locked;
6767
};
6868

69-
static int is_chosen(struct mem_metrics *ctx, const char *proc_path)
69+
static inline int is_empty_choice(struct mk_list *choice)
70+
{
71+
if (choice == NULL || mk_list_size(choice) == 0) {
72+
return FLB_TRUE;
73+
}
74+
return FLB_FALSE;
75+
}
76+
77+
static inline int is_chosen_exec(struct mem_metrics *ctx, const char *proc_path)
7078
{
7179
char real_path[2048] = {0};
7280
char exe_path[2048] = {0};
81+
struct mk_list *head = NULL;
82+
struct flb_slist_entry *cur;
83+
84+
85+
if (is_empty_choice(ctx->chosen_exec)) {
86+
return FLB_FALSE;
87+
}
88+
89+
snprintf(real_path, sizeof(real_path) - 1, "%s/exe", proc_path);
90+
readlink(real_path, exe_path, sizeof(exe_path)-1);
91+
92+
mk_list_foreach(head, ctx->chosen_exec) {
93+
cur = mk_list_entry(head, struct flb_slist_entry, _head);
94+
if (strcmp(exe_path, cur->str) == 0) {
95+
return FLB_TRUE;
96+
}
97+
}
98+
99+
return FLB_FALSE;
100+
}
101+
102+
static inline int is_chosen_cmd(struct mem_metrics *ctx, const char *proc_path)
103+
{
104+
char real_path[2048] = {0};
73105
char cmdline[2048] = {0};
74-
char *ppid;
75-
pid_t pid;
76106
int fd;
77107
int rc;
108+
struct mk_list *head = NULL;
109+
struct flb_slist_entry *cur;
78110

79-
if (ctx->chosen_exec != NULL) {
80-
snprintf(real_path, sizeof(real_path) - 1, "%s/exe", proc_path);
81-
readlink(real_path, exe_path, sizeof(exe_path)-1);
111+
if (is_empty_choice(ctx->chosen_cmd)) {
112+
return FLB_FALSE;
113+
}
82114

83-
if (strcmp(exe_path, ctx->chosen_exec) == 0) {
84-
return FLB_TRUE;
85-
}
115+
snprintf(real_path, sizeof(real_path) - 1, "%s/cmdline", proc_path);
116+
fd = open(real_path, O_RDONLY);
117+
if (fd == -1) {
86118
return FLB_FALSE;
87119
}
88120

89-
if (ctx->chosen_cmd != NULL) {
90-
snprintf(real_path, sizeof(real_path) - 1, "%s/cmdline", proc_path);
91-
fd = open(real_path, O_RDONLY);
92-
if (fd == -1) {
93-
return FLB_FALSE;
94-
}
121+
rc = read(fd, cmdline, sizeof(cmdline)-1);
122+
close(fd);
123+
if (rc == -1) {
124+
return FLB_FALSE;
125+
}
95126

96-
rc = read(fd, cmdline, sizeof(cmdline)-1);
97-
if (rc == -1) {
98-
close(fd);
99-
return FLB_FALSE;
100-
}
101-
close(fd);
102-
cmdline[rc] = '\0';
127+
cmdline[rc] = '\0';
103128

104-
if (strcmp(cmdline, ctx->chosen_cmd) == 0) {
129+
mk_list_foreach(head, ctx->chosen_cmd) {
130+
cur = mk_list_entry(head, struct flb_slist_entry, _head);
131+
if (strcmp(cmdline, cur->str) == 0) {
105132
return FLB_TRUE;
106133
}
134+
}
135+
136+
return FLB_FALSE;
137+
}
138+
139+
static inline int is_chosen_pid(struct mem_metrics *ctx, const char *proc_path)
140+
{
141+
char *pid;
142+
pid_t my_pid = getpid();
143+
pid_t ppid;
144+
struct mk_list *head = NULL;
145+
struct flb_slist_entry *cur;
146+
147+
if (is_empty_choice(ctx->chosen_pid)) {
107148
return FLB_FALSE;
108149
}
109150

110-
if (ctx->chosen_pid != -1) {
111-
ppid = strrchr(proc_path, '/');
112-
if (ppid == NULL) {
113-
return FLB_FALSE;
114-
}
115-
ppid++;
116-
if (ctx->chosen_pid == 0 && strcmp(ppid, "self") == 0) {
151+
pid = strrchr(proc_path, '/');
152+
if (pid == NULL) {
153+
return FLB_FALSE;
154+
}
155+
pid++;
156+
157+
mk_list_foreach(head, ctx->chosen_pid) {
158+
cur = mk_list_entry(head, struct flb_slist_entry, _head);
159+
if (strcmp(pid, cur->str) == 0) {
117160
return FLB_TRUE;
118161
}
119-
pid = strtoul(ppid, NULL, 10);
120-
if (pid == ctx->chosen_pid) {
121-
return FLB_TRUE;
162+
// special case for self and 0
163+
if (strcmp(cur->str, "self") == 0 || strcmp(cur->str, "0") == 0) {
164+
ppid = (pid_t) strtoul(pid, NULL, 10);
165+
if (ppid == my_pid) {
166+
return FLB_TRUE;
167+
}
122168
}
169+
}
170+
171+
return FLB_FALSE;
172+
}
173+
174+
static inline int is_chosen_pid_self(struct mem_metrics *ctx)
175+
{
176+
struct mk_list *head = NULL;
177+
struct flb_slist_entry *cur;
178+
179+
if (ctx->chosen_pid == NULL) {
123180
return FLB_FALSE;
124181
}
125182

126-
return FLB_TRUE;
183+
if (mk_list_size(ctx->chosen_pid) != 1) {
184+
return FLB_FALSE;
185+
}
186+
187+
mk_list_foreach(head, ctx->chosen_pid) {
188+
cur = mk_list_entry(head, struct flb_slist_entry, _head);
189+
// special case for self and 0
190+
if (strcmp(cur->str, "self") == 0 || strcmp(cur->str, "0") == 0) {
191+
return FLB_TRUE;
192+
}
193+
}
194+
195+
return FLB_FALSE;
196+
}
197+
198+
static int is_chosen(struct mem_metrics *ctx, const char *proc_path)
199+
{
200+
// choose all processes if no filters are set.
201+
if (is_empty_choice(ctx->chosen_cmd) &&
202+
is_empty_choice(ctx->chosen_exec) &&
203+
is_empty_choice(ctx->chosen_pid)) {
204+
return FLB_TRUE;
205+
}
206+
207+
if (is_chosen_exec(ctx, proc_path) == FLB_TRUE) {
208+
return FLB_TRUE;
209+
}
210+
211+
if (is_chosen_cmd(ctx, proc_path) == FLB_TRUE) {
212+
return FLB_TRUE;
213+
}
214+
215+
if (is_chosen_pid(ctx, proc_path) == FLB_TRUE) {
216+
return FLB_TRUE;
217+
}
218+
219+
// filters are set and none have been chosen.
220+
return FLB_FALSE;
127221
}
128222

129223
static void mmtx_parse_proc(struct mem_metrics *ctx, uint64_t ts, const char *proc_path)
@@ -149,7 +243,7 @@ static void mmtx_parse_proc(struct mem_metrics *ctx, uint64_t ts, const char *pr
149243
return;
150244
}
151245
pid++;
152-
246+
153247
snprintf(real_path, sizeof(real_path) - 1, "%s/smaps_rollup", proc_path);
154248
fd = open(real_path, O_RDONLY);
155249
if (fd == -1) {
@@ -175,7 +269,7 @@ static void mmtx_parse_proc(struct mem_metrics *ctx, uint64_t ts, const char *pr
175269
if (sep == NULL) {
176270
continue;
177271
}
178-
val = strtoul(sep+1, NULL, 10);
272+
val = strtoul(sep+1, NULL, 10);
179273

180274
if (strncasecmp(cur->value, "Rss:", sep - cur->value) == 0) {
181275
cmt_gauge_set(ctx->rss, ts, val, 1, (char *[]){ pid });
@@ -315,10 +409,10 @@ static int cb_collector_time(struct flb_input_instance *ins,
315409
struct flb_config *config, void *in_context)
316410
{
317411
struct mem_metrics *ctx = (struct mem_metrics *)in_context;
318-
if (ctx->chosen_pid == 0) {
319-
mmtx_parse_proc(ctx, cfl_time_now(), "/proc/self");
412+
if (is_chosen_pid_self(ctx)) {
413+
mmtx_parse_proc(ctx, cfl_time_now(), "/proc/self");
320414
} else {
321-
mmtx_utils_path_scan_procs(ctx, cfl_time_now());
415+
mmtx_utils_path_scan_procs(ctx, cfl_time_now());
322416
}
323417
flb_input_metrics_append(ins, NULL, 0, ctx->cmt);
324418
FLB_INPUT_RETURN(0);
@@ -414,17 +508,17 @@ static struct flb_config_map config_map[] = {
414508
"The path of the proc pseudo filesystem, default: /proc"
415509
},
416510
{
417-
FLB_CONFIG_MAP_STR, "filter_exec", NULL,
511+
FLB_CONFIG_MAP_CLIST_1, "filter_exec", NULL,
418512
0, FLB_TRUE, offsetof(struct mem_metrics, chosen_exec),
419513
"Filter for a single executable"
420514
},
421515
{
422-
FLB_CONFIG_MAP_STR, "filter_cmd", NULL,
516+
FLB_CONFIG_MAP_CLIST_1, "filter_cmd", NULL,
423517
0, FLB_TRUE, offsetof(struct mem_metrics, chosen_cmd),
424518
"Filter by the command line"
425519
},
426520
{
427-
FLB_CONFIG_MAP_INT, "filter_pid", "-1",
521+
FLB_CONFIG_MAP_CLIST_1, "filter_pid", NULL,
428522
0, FLB_TRUE, offsetof(struct mem_metrics, chosen_pid),
429523
"Filter by PID"
430524
},

0 commit comments

Comments
 (0)