@cryptotaxi247 / netdata-1 / commits / f8e243153

extending procfile parsing to support quotes and opening/closing characters #234; proper fix for apps.plugin incorrectly logging to syslog #225

Costa Tsaousis (ktsaou) committed Apr 16, 2016 at 06:02 UTC f8e24315326151a7c5625ca2b0209c995236c140
3 files changed +153 -39
src/apps_plugin.c
+30 -32
@@ -37,6 +37,7 @@
37 #include "common.h"
38 #include "log.h"
39 #include "procfile.h"
40 +#include "../config.h"
41
42 #define MAX_COMPARE_NAME 15
43 #define MAX_NAME 100
@@ -53,9 +54,6 @@ unsigned long long file_counter = 0;
54 char *host_prefix = "";
55 char *config_dir = CONFIG_DIR;
56
56 -// disable syslog for apps.plugin
57 -int error_log_syslog = 0;
58 -
57 #ifdef NETDATA_INTERNAL_CHECKS
58 // ----------------------------------------------------------------------------
59 // memory debugger
@@ -216,20 +214,20 @@ char *strdup_debug(const char *file, int line, const char *function, const char
214 // system functions
215 // to retrieve settings of the system
216
219 -procfile *ff = NULL;
220 -
217 long get_system_cpus(void) {
218 + procfile *ff = NULL;
219 +
220 int processors = 0;
221
222 char filename[FILENAME_MAX + 1];
223 snprintf(filename, FILENAME_MAX, "%s/proc/stat", host_prefix);
224
227 - ff = procfile_reopen(ff, filename, "", PROCFILE_FLAG_DEFAULT);
225 + ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
226 if(!ff) return 1;
227
228 ff = procfile_readall(ff);
229 if(!ff) {
232 - // procfile_close(ff);
230 + procfile_close(ff);
231 return 1;
232 }
233
@@ -242,28 +240,29 @@ long get_system_cpus(void) {
240 processors--;
241 if(processors < 1) processors = 1;
242
245 - // procfile_close(ff);
243 + procfile_close(ff);
244 return processors;
245 }
246
247 long get_system_pid_max(void) {
248 + procfile *ff = NULL;
249 long mpid = 32768;
250
251 char filename[FILENAME_MAX + 1];
252 snprintf(filename, FILENAME_MAX, "%s/proc/sys/kernel/pid_max", host_prefix);
254 - ff = procfile_reopen(ff, filename, "", PROCFILE_FLAG_DEFAULT);
253 + ff = procfile_open(filename, NULL, PROCFILE_FLAG_DEFAULT);
254 if(!ff) return mpid;
255
256 ff = procfile_readall(ff);
257 if(!ff) {
259 - // procfile_close(ff);
258 + procfile_close(ff);
259 return mpid;
260 }
261
262 mpid = atol(procfile_lineword(ff, 0, 0));
263 if(!mpid) mpid = 32768;
264
266 - // procfile_close(ff);
265 + procfile_close(ff);
266 return mpid;
267 }
268
@@ -594,6 +593,7 @@ int read_apps_groups_conf(const char *name)
593 struct pid_stat {
594 int32_t pid;
595 char comm[MAX_COMPARE_NAME + 1];
596 +
597 // char state;
598 int32_t ppid;
599 // int32_t pgrp;
@@ -786,15 +786,22 @@ int read_proc_pid_ownership(struct pid_stat *p) {
786 }
787
788 int read_proc_pid_stat(struct pid_stat *p) {
789 + static procfile *ff = NULL;
790 +
791 char filename[FILENAME_MAX + 1];
792
793 snprintf(filename, FILENAME_MAX, "%s/proc/%d/stat", host_prefix, p->pid);
794
795 // ----------------------------------------
796
797 + int set_quotes = (!ff)?1:0;
798 +
799 ff = procfile_reopen(ff, filename, NULL, PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
800 if(!ff) return 1;
801
802 + // if(set_quotes) procfile_set_quotes(ff, "()");
803 + if(set_quotes) procfile_set_open_close(ff, "(", ")");
804 +
805 ff = procfile_readall(ff);
806 if(!ff) {
807 // procfile_close(ff);
@@ -803,27 +810,10 @@ int read_proc_pid_stat(struct pid_stat *p) {
810
811 file_counter++;
812
806 - p->comm[0] = '\0';
813 + // parse the process name
814 + unsigned int i = 1;
815 + strncpy(p->comm, procfile_lineword(ff, 0, i), MAX_COMPARE_NAME);
816 p->comm[MAX_COMPARE_NAME] = '\0';
808 - size_t blen = 0;
809 -
810 - char *s = procfile_lineword(ff, 0, 1);
811 - if(*s == '(') s++;
812 - size_t len = strlen(s);
813 - unsigned int i = 0;
814 - while(len && s[len - 1] != ')') {
815 - if(blen < MAX_COMPARE_NAME) {
816 - strncpy(&p->comm[blen], s, MAX_COMPARE_NAME - blen);
817 - blen = strlen(p->comm);
818 - }
819 -
820 - i++;
821 - s = procfile_lineword(ff, 0, 1+i);
822 - len = strlen(s);
823 - }
824 - if(len && s[len - 1] == ')') s[len - 1] = '\0';
825 - if(blen < MAX_COMPARE_NAME)
826 - strncpy(&p->comm[blen], s, MAX_COMPARE_NAME - blen);
817
818 // p->pid = atol(procfile_lineword(ff, 0, 0+i));
819 // comm is at 1
@@ -870,13 +860,16 @@ int read_proc_pid_stat(struct pid_stat *p) {
860 // p->guest_time = strtoull(procfile_lineword(ff, 0, 42+i), NULL, 10);
861 // p->cguest_time = strtoull(procfile_lineword(ff, 0, 43), NULL, 10);
862
873 - if(debug || (p->target && p->target->debug)) fprintf(stderr, "apps.plugin: VALUES: %s utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, threads=%d\n", p->comm, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
863 + if(debug || (p->target && p->target->debug))
864 + fprintf(stderr, "apps.plugin: READ PROC/PID/STAT: %s/proc/%d/stat, process: '%s' VALUES: utime=%llu, stime=%llu, cutime=%llu, cstime=%llu, minflt=%llu, majflt=%llu, cminflt=%llu, cmajflt=%llu, threads=%d\n", host_prefix, p->pid, p->comm, p->utime, p->stime, p->cutime, p->cstime, p->minflt, p->majflt, p->cminflt, p->cmajflt, p->num_threads);
865
866 // procfile_close(ff);
867 return 0;
868 }
869
870 int read_proc_pid_statm(struct pid_stat *p) {
871 + static procfile *ff = NULL;
872 +
873 char filename[FILENAME_MAX + 1];
874
875 snprintf(filename, FILENAME_MAX, "%s/proc/%d/statm", host_prefix, p->pid);
@@ -905,6 +898,8 @@ int read_proc_pid_statm(struct pid_stat *p) {
898 }
899
900 int read_proc_pid_io(struct pid_stat *p) {
901 + static procfile *ff = NULL;
902 +
903 char filename[FILENAME_MAX + 1];
904
905 snprintf(filename, FILENAME_MAX, "%s/proc/%d/io", host_prefix, p->pid);
@@ -2370,6 +2365,9 @@ int main(int argc, char **argv)
2365 // set the name for logging
2366 program_name = "apps.plugin";
2367
2368 + // disable syslog for apps.plugin
2369 + error_log_syslog = 0;
2370 +
2371 host_prefix = getenv("NETDATA_HOST_PREFIX");
2372 if(host_prefix == NULL) {
2373 info("NETDATA_HOST_PREFIX is not passed from netdata");
src/procfile.c
+120 -7
@@ -20,6 +20,7 @@
20 #include "common.h"
21 #include "log.h"
22 #include "procfile.h"
23 +#include "../config.h"
24
25 #define PF_PREFIX "PROCFILE"
26
@@ -142,6 +143,9 @@ void pflines_free(pflines *fl) {
143 #define PF_CHAR_IS_SEPARATOR ' '
144 #define PF_CHAR_IS_NEWLINE 'N'
145 #define PF_CHAR_IS_WORD 'W'
146 +#define PF_CHAR_IS_QUOTE 'Q'
147 +#define PF_CHAR_IS_OPEN 'O'
148 +#define PF_CHAR_IS_CLOSE 'C'
149
150 void procfile_close(procfile *ff) {
151 debug(D_PROCFILE, PF_PREFIX ": Closing file '%s'", ff->filename);
@@ -156,17 +160,82 @@ void procfile_close(procfile *ff) {
160 procfile *procfile_parser(procfile *ff) {
161 debug(D_PROCFILE, PF_PREFIX ": Parsing file '%s'", ff->filename);
162
159 - char *s = ff->data, *e = ff->data, *t = ff->data;
163 + char *s = ff->data, *e = &ff->data[ff->len], *t = ff->data, quote = 0;
164 uint32_t l = 0, w = 0;
161 - e += ff->len;
165 + int opened = 0;
166
167 ff->lines = pflines_add(ff->lines, w);
168 if(unlikely(!ff->lines)) goto cleanup;
169
170 while(likely(s < e)) {
171 + // we are not at the end
172 +
173 switch(ff->separators[(int)(*s)]) {
174 + case PF_CHAR_IS_OPEN:
175 + if(s == t) {
176 + opened++;
177 + t = ++s;
178 + }
179 + else if(opened) {
180 + opened++;
181 + s++;
182 + }
183 + else
184 + s++;
185 + continue;
186 +
187 + case PF_CHAR_IS_CLOSE:
188 + if(opened) {
189 + opened--;
190 +
191 + if(!opened) {
192 + *s = '\0';
193 + ff->words = pfwords_add(ff->words, t);
194 + if(unlikely(!ff->words)) goto cleanup;
195 +
196 + ff->lines->lines[l].words++;
197 + w++;
198 +
199 + t = ++s;
200 + }
201 + else
202 + s++;
203 + }
204 + else
205 + s++;
206 + continue;
207 +
208 + case PF_CHAR_IS_QUOTE:
209 + if(unlikely(!quote && s == t)) {
210 + // quote opened at the beginning
211 + quote = *s;
212 + t = ++s;
213 + }
214 + else if(unlikely(quote && quote == *s)) {
215 + // quote closed
216 + quote = 0;
217 +
218 + *s = '\0';
219 + ff->words = pfwords_add(ff->words, t);
220 + if(unlikely(!ff->words)) goto cleanup;
221 +
222 + ff->lines->lines[l].words++;
223 + w++;
224 +
225 + t = ++s;
226 + }
227 + else
228 + s++;
229 + continue;
230 +
231 case PF_CHAR_IS_SEPARATOR:
169 - if(likely(s == t)) {
232 + if(unlikely(quote || opened)) {
233 + // we are inside a quote
234 + s++;
235 + continue;
236 + }
237 +
238 + if(unlikely(s == t)) {
239 // skip all leading white spaces
240 t = ++s;
241 continue;
@@ -209,9 +278,10 @@ procfile *procfile_parser(procfile *ff) {
278 }
279 }
280
212 - if(likely(s != t)) {
281 + if(likely(s > t && t < e)) {
282 // the last word
214 - if(likely(ff->len < ff->size)) *s = '\0';
283 + if(likely(ff->len < ff->size))
284 + *s = '\0';
285 else {
286 // we are going to loose the last byte
287 ff->data[ff->size - 1] = '\0';
@@ -309,10 +379,53 @@ static void procfile_set_separators(procfile *ff, const char *separators) {
379 while(likely(ffd != ffe)) *ffs++ = *ffd++;
380
381 // set the separators
312 - if(unlikely(!separators)) separators = " \t=|";
382 + if(unlikely(!separators))
383 + separators = " \t=|";
384 +
385 ffs = ff->separators;
386 const char *s = separators;
315 - while(likely(*s)) ffs[(int)*s++] = PF_CHAR_IS_SEPARATOR;
387 + while(likely(*s))
388 + ffs[(int)*s++] = PF_CHAR_IS_SEPARATOR;
389 +}
390 +
391 +void procfile_set_quotes(procfile *ff, const char *quotes) {
392 + // remove all quotes
393 + int i;
394 + for(i = 0; i < 256 ; i++)
395 + if(ff->separators[i] == PF_CHAR_IS_QUOTE)
396 + ff->separators[i] = PF_CHAR_IS_WORD;
397 +
398 + // if nothing given, return
399 + if(unlikely(!quotes || !*quotes))
400 + return;
401 +
402 + // set the quotes
403 + char *ffs = ff->separators;
404 + const char *s = quotes;
405 + while(likely(*s))
406 + ffs[(int)*s++] = PF_CHAR_IS_QUOTE;
407 +}
408 +
409 +void procfile_set_open_close(procfile *ff, const char *open, const char *close) {
410 + // remove all open/close
411 + int i;
412 + for(i = 0; i < 256 ; i++)
413 + if(ff->separators[i] == PF_CHAR_IS_OPEN || ff->separators[i] == PF_CHAR_IS_CLOSE)
414 + ff->separators[i] = PF_CHAR_IS_WORD;
415 +
416 + // if nothing given, return
417 + if(unlikely(!open || !*open || !close || !*close))
418 + return;
419 +
420 + // set the openings
421 + char *ffs = ff->separators;
422 + const char *s = open;
423 + while(likely(*s))
424 + ffs[(int)*s++] = PF_CHAR_IS_OPEN;
425 +
426 + s = close;
427 + while(likely(*s))
428 + ffs[(int)*s++] = PF_CHAR_IS_CLOSE;
429 }
430
431 procfile *procfile_open(const char *filename, const char *separators, uint32_t flags) {
src/procfile.h
+3
@@ -86,6 +86,9 @@ extern procfile *procfile_reopen(procfile *ff, const char *filename, const char
86 // example walk-through a procfile parsed file
87 extern void procfile_print(procfile *ff);
88
89 +extern void procfile_set_quotes(procfile *ff, const char *quotes);
90 +extern void procfile_set_open_close(procfile *ff, const char *open, const char *close);
91 +
92 // ----------------------------------------------------------------------------
93
94 // set this to 1, to have procfile adapt its initial buffer allocation to the max allocation used so far