@cryptotaxi247 / netdata-1 / commits / a4a116788

preparations for statsd apps configuration

Costa Tsaousis (ktsaou) committed May 1, 2017 at 01:34 UTC a4a116788ef3e926049987f406eaa80890980db2
5 files changed +145 -46
src/appconfig.c
+2 -2
@@ -452,7 +452,7 @@ int appconfig_load(struct config *root, char *filename, int overwrite_used)
452 line++;
453
454 s = trim(buffer);
455 - if(!s) {
455 + if(!s || *s == '#') {
456 debug(D_CONFIG, "Ignoring line %d, it is empty.", line);
457 continue;
458 }
@@ -487,7 +487,7 @@ int appconfig_load(struct config *root, char *filename, int overwrite_used)
487 name = trim(name);
488 value = trim(value);
489
490 - if(!name) {
490 + if(!name || *name == '#') {
491 error("Ignoring line %d, name is empty.", line);
492 continue;
493 }
src/common.c
+32 -2
@@ -895,9 +895,8 @@ char *mystrsep(char **ptr, char *s) {
895
896 char *trim(char *s) {
897 // skip leading spaces
898 - // and 'comments' as well!?
898 while (*s && isspace(*s)) s++;
900 - if (!*s || *s == '#') return NULL;
899 + if (!*s) return NULL;
900
901 // skip tailing spaces
902 // this way is way faster. Writes only one NUL char.
@@ -913,6 +912,37 @@ char *trim(char *s) {
912 return s;
913 }
914
915 +inline char *trim_all(char *buffer) {
916 + char *d = buffer, *s = buffer;
917 +
918 + // skip spaces
919 + while(isspace(*s)) s++;
920 +
921 + while(*s) {
922 + // copy the non-space part
923 + while(*s && !isspace(*s)) *d++ = *s++;
924 +
925 + // add a space if we have to
926 + if(*s && isspace(*s)) {
927 + *d++ = ' ';
928 + s++;
929 + }
930 +
931 + // skip spaces
932 + while(isspace(*s)) s++;
933 + }
934 +
935 + *d = '\0';
936 +
937 + if(d > buffer) {
938 + d--;
939 + if(isspace(*d)) *d = '\0';
940 + }
941 +
942 + if(!buffer[0]) return NULL;
943 + return buffer;
944 +}
945 +
946 void *mymmap(const char *filename, size_t size, int flags, int ksm) {
947 #ifndef MADV_MERGEABLE
948 (void)ksm;
src/common.h
+2 -1
@@ -241,7 +241,8 @@ extern void netdata_fix_chart_name(char *s);
241
242 extern void strreverse(char* begin, char* end);
243 extern char *mystrsep(char **ptr, char *s);
244 -extern char *trim(char *s);
244 +extern char *trim(char *s); // remove leading and trailing spaces; may return NULL
245 +extern char *trim_all(char *buffer); // like trim(), but also remove duplicate spaces inside the string; may return NULL
246
247 extern int vsnprintfz(char *dst, size_t n, const char *fmt, va_list args);
248 extern int snprintfz(char *dst, size_t n, const char *fmt, ...) PRINTFLIKE(3, 4);
src/health_config.c
+5 -36
@@ -241,10 +241,10 @@ static inline int health_parse_delay(
241
242 if(!given_max) {
243 if((*delay_max_duration) < (*delay_up_duration) * (*delay_multiplier))
244 - *delay_max_duration = (*delay_up_duration) * (*delay_multiplier);
244 + *delay_max_duration = (int)((*delay_up_duration) * (*delay_multiplier));
245
246 if((*delay_max_duration) < (*delay_down_duration) * (*delay_multiplier))
247 - *delay_max_duration = (*delay_down_duration) * (*delay_multiplier);
247 + *delay_max_duration = (int)((*delay_down_duration) * (*delay_multiplier));
248 }
249
250 return 1;
@@ -381,37 +381,6 @@ static inline int health_parse_db_lookup(
381 return 1;
382 }
383
384 -static inline char *trim_all_spaces(char *buffer) {
385 - char *d = buffer, *s = buffer;
386 -
387 - // skip spaces
388 - while(isspace(*s)) s++;
389 -
390 - while(*s) {
391 - // copy the non-space part
392 - while(*s && !isspace(*s)) *d++ = *s++;
393 -
394 - // add a space if we have to
395 - if(*s && isspace(*s)) {
396 - *d++ = ' ';
397 - s++;
398 - }
399 -
400 - // skip spaces
401 - while(isspace(*s)) s++;
402 - }
403 -
404 - *d = '\0';
405 -
406 - if(d > buffer) {
407 - d--;
408 - if(isspace(*d)) *d = '\0';
409 - }
410 -
411 - if(!buffer[0]) return NULL;
412 - return buffer;
413 -}
414 -
384 static inline char *health_source_file(size_t line, const char *path, const char *filename) {
385 char buffer[FILENAME_MAX + 1];
386 snprintfz(buffer, FILENAME_MAX, "%zu@%s/%s", line, path, filename);
@@ -485,7 +454,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
454 int stop_appending = !s;
455 line++;
456 s = trim(buffer);
488 - if(!s) continue;
457 + if(!s || *s == '#') continue;
458
459 append = strlen(s);
460 if(!stop_appending && s[append - 1] == '\\') {
@@ -509,8 +478,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) {
478 s++;
479
480 char *value = s;
512 - key = trim_all_spaces(key);
513 - value = trim_all_spaces(value);
481 + key = trim_all(key);
482 + value = trim_all(value);
483
484 if(!key) {
485 error("Health configuration has invalid line %zu of file '%s/%s'. Keyword is empty. Ignoring it.", line, path, filename);
src/statsd.c
+104 -5
@@ -70,11 +70,11 @@ typedef struct statsd_metric_set {
70 // this is a metric - for all types of metrics
71
72 typedef enum statsd_metric_options {
73 - STATSD_METRIC_OPTION_NONE = 0x00000000,
74 - STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED = 0x00000001,
75 - STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED = 0x00000002,
76 - STATSD_METRIC_OPTION_PRIVATE_CHART_DISABLED = 0x00000004,
77 - STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT = 0x00000008,
73 + STATSD_METRIC_OPTION_NONE = 0x00000000, // no options set
74 + STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED = 0x00000001, // do not update the chart dimension, when this metric is not collected
75 + STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED = 0x00000002, // render a private chart for this metric
76 + STATSD_METRIC_OPTION_PRIVATE_CHART_DISABLED = 0x00000004, // do not render a private chart for this metric
77 + STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT = 0x00000008, // show the count of events for this private chart
78 } STATS_METRIC_OPTIONS;
79
80 typedef struct statsd_metric {
@@ -126,6 +126,47 @@ typedef struct statsd_index {
126
127 static int statsd_metric_compare(void* a, void* b);
128
129 +// --------------------------------------------------------------------------------------------------------------------
130 +// synthetic charts
131 +
132 +typedef struct statsd_app_chart_dim {
133 + const char *name;
134 + const char *metric;
135 + uint32_t metric_hash;
136 + collected_number multiplier;
137 + collected_number divider;
138 + STATSD_INDEX *index;
139 +
140 + STATSD_METRIC *m;
141 + RRDDIM *rd;
142 + struct statsd_app_chart_dim *next;
143 +} STATSD_APP_CHART_DIM;
144 +
145 +typedef struct statsd_app_chart {
146 + const char *source;
147 + const char *id;
148 + const char *name;
149 + const char *title;
150 + const char *family;
151 + const char *context;
152 + const char *units;
153 + long priority;
154 + RRDSET_TYPE chart_type;
155 + STATSD_APP_CHART_DIM *dimensions;
156 +
157 + RRDSET *st;
158 + struct statsd_app_chart *next;
159 +} STATSD_APP_CHART;
160 +
161 +typedef struct statsd_app {
162 + const char *name;
163 + SIMPLE_PATTERN *metrics;
164 + STATS_METRIC_OPTIONS default_options;
165 +
166 + const char *source;
167 + STATSD_APP_CHART *charts;
168 + struct statsd_app *next;
169 +} STATSD_APP;
170
171 // --------------------------------------------------------------------------------------------------------------------
172 // global statsd data
@@ -156,6 +197,7 @@ static struct statsd {
197 RRD_MEMORY_MODE private_charts_memory_mode;
198 int private_charts_history;
199
200 + STATSD_APP *apps;
201 size_t recvmmsg_size;
202 size_t histogram_increase_step;
203 double histogram_percentile;
@@ -223,6 +265,7 @@ static struct statsd {
265 STATSD_FIRST_PTR_MUTEX_INIT
266 },
267
268 + .apps = NULL,
269 .histogram_percentile = 95.0,
270 .histogram_increase_step = 10,
271 .threads = 0,
@@ -859,6 +902,62 @@ void *statsd_collector_thread(void *ptr) {
902 }
903
904
905 +// --------------------------------------------------------------------------------------------------------------------
906 +// statsd applications configuration files parsing
907 +
908 +#define STATSD_CONF_MAX_LINE 8192
909 +
910 +int statsd_readfile(const char *path, const char *filename) {
911 + debug(D_STATSD, "STATSD configuration reading file '%s/%s'", path, filename);
912 + // FIXME
913 + return 1;
914 +}
915 +
916 +static void statsd_readdir(const char *path) {
917 + size_t pathlen = strlen(path);
918 +
919 + debug(D_STATSD, "STATSD configuration reading directory '%s'", path);
920 +
921 + DIR *dir = opendir(path);
922 + if (!dir) {
923 + error("STATSD configuration cannot open directory '%s'.", path);
924 + return;
925 + }
926 +
927 + struct dirent *de = NULL;
928 + while ((de = readdir(dir))) {
929 + size_t len = strlen(de->d_name);
930 +
931 + if(de->d_type == DT_DIR
932 + && (
933 + (de->d_name[0] == '.' && de->d_name[1] == '\0')
934 + || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')
935 + )) {
936 + debug(D_STATSD, "STATSD: ignoring directory '%s'", de->d_name);
937 + continue;
938 + }
939 +
940 + else if(de->d_type == DT_DIR) {
941 + char *s = mallocz(pathlen + strlen(de->d_name) + 2);
942 + strcpy(s, path);
943 + strcat(s, "/");
944 + strcat(s, de->d_name);
945 + statsd_readdir(s);
946 + freez(s);
947 + continue;
948 + }
949 +
950 + else if((de->d_type == DT_LNK || de->d_type == DT_REG || de->d_type == DT_UNKNOWN) &&
951 + len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) {
952 + statsd_readfile(path, de->d_name);
953 + }
954 +
955 + else debug(D_STATSD, "STATSD: ignoring file '%s'", de->d_name);
956 + }
957 +
958 + closedir(dir);
959 +}
960 +
961 // --------------------------------------------------------------------------------------------------------------------
962 // send metrics to netdata - in private charts - called from the main thread
963