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