@cryptotaxi247 / netdata-1 / commits / b2230fef1

added visualization for histograms and timers

Costa Tsaousis (ktsaou) committed Apr 27, 2017 at 01:16 UTC b2230fef11da10f7625172b4d709fec739d17651
4 files changed +137 -11
src/appconfig.c
+21
@@ -295,6 +295,17 @@ long long appconfig_get_number(struct config *root, const char *section, const c
295 return strtoll(s, NULL, 0);
296 }
297
298 +long double appconfig_get_float(struct config *root, const char *section, const char *name, long double value)
299 +{
300 + char buffer[100], *s;
301 + sprintf(buffer, "%0.5Lf", value);
302 +
303 + s = appconfig_get(root, section, name, buffer);
304 + if(!s) return value;
305 +
306 + return strtold(s, NULL);
307 +}
308 +
309 int appconfig_get_boolean(struct config *root, const char *section, const char *name, int value)
310 {
311 char *s;
@@ -394,6 +405,16 @@ long long appconfig_set_number(struct config *root, const char *section, const c
405 return value;
406 }
407
408 +long double appconfig_set_float(struct config *root, const char *section, const char *name, long double value)
409 +{
410 + char buffer[100];
411 + sprintf(buffer, "%0.5Lf", value);
412 +
413 + appconfig_set(root, section, name, buffer);
414 +
415 + return value;
416 +}
417 +
418 int appconfig_set_boolean(struct config *root, const char *section, const char *name, int value)
419 {
420 char *s;
src/appconfig.h
+4
@@ -35,12 +35,14 @@ extern int appconfig_load(struct config *root, char *filename, int overwrite_use
35
36 extern char *appconfig_get(struct config *root, const char *section, const char *name, const char *default_value);
37 extern long long appconfig_get_number(struct config *root, const char *section, const char *name, long long value);
38 +extern long double appconfig_get_float(struct config *root, const char *section, const char *name, long double value);
39 extern int appconfig_get_boolean(struct config *root, const char *section, const char *name, int value);
40 extern int appconfig_get_boolean_ondemand(struct config *root, const char *section, const char *name, int value);
41
42 extern const char *appconfig_set(struct config *root, const char *section, const char *name, const char *value);
43 extern const char *appconfig_set_default(struct config *root, const char *section, const char *name, const char *value);
44 extern long long appconfig_set_number(struct config *root, const char *section, const char *name, long long value);
45 +extern long double appconfig_set_float(struct config *root, const char *section, const char *name, long double value);
46 extern int appconfig_set_boolean(struct config *root, const char *section, const char *name, int value);
47
48 extern int appconfig_exists(struct config *root, const char *section, const char *name);
@@ -54,12 +56,14 @@ extern void appconfig_generate(struct config *root, BUFFER *wb, int only_changed
56 #define config_load(filename, overwrite_used) appconfig_load(&netdata_config, filename, overwrite_used)
57 #define config_get(section, name, default_value) appconfig_get(&netdata_config, section, name, default_value)
58 #define config_get_number(section, name, value) appconfig_get_number(&netdata_config, section, name, value)
59 +#define config_get_float(section, name, value) appconfig_get_float(&netdata_config, section, name, value)
60 #define config_get_boolean(section, name, value) appconfig_get_boolean(&netdata_config, section, name, value)
61 #define config_get_boolean_ondemand(section, name, value) appconfig_get_boolean_ondemand(&netdata_config, section, name, value)
62
63 #define config_set(section, name, default_value) appconfig_set(&netdata_config, section, name, default_value)
64 #define config_set_default(section, name, value) appconfig_set_default(&netdata_config, section, name, value)
65 #define config_set_number(section, name, value) appconfig_set_number(&netdata_config, section, name, value)
66 +#define config_set_float(section, name, value) appconfig_set_float(&netdata_config, section, name, value)
67 #define config_set_boolean(section, name, value) appconfig_set_boolean(&netdata_config, section, name, value)
68
69 #define config_exists(section, name) appconfig_exists(&netdata_config, section, name)
src/socket.c
+3
@@ -978,5 +978,8 @@ void poll_events(LISTEN_SOCKETS *sockets
978 }
979 }
980 }
981 +
982 + freez(p.fds);
983 + freez(p.inf);
984 }
985
src/statsd.c
+109 -11
@@ -38,10 +38,21 @@ typedef struct statsd_metric_counter { // counter and meter
38 long long value;
39 } STATSD_METRIC_COUNTER;
40
41 -typedef struct statsd_metric_histogram { // histogram and timer
41 +typedef struct statsd_histogram_extensions {
42 size_t size;
43 size_t used;
44 - long double *values; // dynamic array of values collected
44 + collected_number last_min;
45 + collected_number last_max;
46 + collected_number last_pct;
47 + RRDDIM *rd_min;
48 + RRDDIM *rd_max;
49 + RRDDIM *rd_pct;
50 + long double values[]; // dynamic array of values collected
51 +} STATSD_METRIC_HISTOGRAM_EXTENSIONS;
52 +
53 +typedef struct statsd_metric_histogram { // histogram and timer
54 + netdata_mutex_t mutex;
55 + STATSD_METRIC_HISTOGRAM_EXTENSIONS *ext;
56 } STATSD_METRIC_HISTOGRAM;
57
58 typedef struct statsd_metric_set {
@@ -133,6 +144,8 @@ static struct statsd {
144 int private_charts_history;
145
146 size_t histogram_increase_step;
147 + double histogram_percentile;
148 + char *histogram_percentile_str;
149 int threads;
150 LISTEN_SOCKETS sockets;
151 } statsd = {
@@ -196,6 +209,7 @@ static struct statsd {
209 STATSD_FIRST_PTR_MUTEX_INIT
210 },
211
212 + .histogram_percentile = 95.0,
213 .histogram_increase_step = 10,
214 .threads = 0,
215 .sockets = {
@@ -248,6 +262,12 @@ static inline STATSD_METRIC *statsd_find_or_add_metric(STATSD_INDEX *index, char
262 index->metrics++;
263 m->next = index->first;
264 index->first = m;
265 +
266 + if(index == &statsd.histograms || index == &statsd.timers) {
267 + m->histogram.ext = callocz(sizeof(STATSD_METRIC_HISTOGRAM_EXTENSIONS), 1);
268 + netdata_mutex_init(&m->histogram.mutex);
269 + }
270 +
271 STATSD_FIRST_PTR_MUTEX_UNLOCK(index);
272 }
273 }
@@ -338,16 +358,18 @@ static inline void statsd_process_histogram(STATSD_METRIC *m, char *v, char *r)
358 }
359
360 if(unlikely(m->reset)) {
341 - m->histogram.used = 0;
361 + m->histogram.ext->used = 0;
362 statsd_reset_metric(m);
363 }
364
345 - if(m->histogram.used == m->histogram.size) {
346 - m->histogram.size += statsd.histogram_increase_step;
347 - m->histogram.values = reallocz(m->histogram.values, sizeof(long double) * m->histogram.size);
365 + if(m->histogram.ext->used == m->histogram.ext->size) {
366 + netdata_mutex_lock(&m->histogram.mutex);
367 + m->histogram.ext->size += statsd.histogram_increase_step;
368 + m->histogram.ext = reallocz(m->histogram.ext, sizeof(STATSD_METRIC_HISTOGRAM_EXTENSIONS) + (sizeof(long double) * m->histogram.ext->size));
369 + netdata_mutex_unlock(&m->histogram.mutex);
370 }
371
350 - m->histogram.values[m->histogram.used++] = statsd_parse_float(v, 1.0) / statsd_parse_float(r, 1.0);
372 + m->histogram.ext->values[m->histogram.ext->used++] = statsd_parse_float(v, 1.0) / statsd_parse_float(r, 1.0);
373
374 m->events++;
375 m->count++;
@@ -690,7 +712,7 @@ void *statsd_collector_thread(void *ptr) {
712
713
714 // --------------------------------------------------------------------------------------------------------------------
693 -// send metrics to netdata - called from the main thread
715 +// send metrics to netdata - in private charts - called from the main thread
716
717 #define STATSD_CHART_PREFIX "statsd"
718 #define STATSD_CHART_PRIORITY 90000
@@ -877,7 +899,72 @@ static inline void statsd_chart_from_set(STATSD_METRIC *m) {
899 rrdset_done(m->st);
900 }
901
880 -static inline void statsd_private_charts_from_index(STATSD_INDEX *index, void (*chart_from_metric)(STATSD_METRIC *m)) {
902 +static inline void statsd_chart_from_timer_or_histogram(STATSD_METRIC *m, char *dim, char *family) {
903 + if(unlikely(!m->st)) {
904 + char type[RRD_ID_LENGTH_MAX + 1], id[RRD_ID_LENGTH_MAX + 1];
905 + statsd_get_metric_type_and_id(m, type, id, dim, RRD_ID_LENGTH_MAX);
906 +
907 + m->st = statsd_private_rrdset_create(
908 + m
909 + , type
910 + , id
911 + , NULL // name
912 + , family // family (submenu)
913 + , m->name // context
914 + , m->name // title
915 + , "events/s" // units
916 + , STATSD_CHART_PRIORITY
917 + , statsd.update_every
918 + , RRDSET_TYPE_AREA
919 + );
920 +
921 + m->histogram.ext->rd_min = rrddim_add(m->st, "min", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
922 + m->histogram.ext->rd_max = rrddim_add(m->st, "max", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
923 + m->rd_value = rrddim_add(m->st, "avg", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
924 + m->histogram.ext->rd_pct = rrddim_add(m->st, statsd.histogram_percentile_str, NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
925 +
926 + if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT)
927 + m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
928 + }
929 + else rrdset_next(m->st);
930 +
931 + if(m->count && !m->reset) {
932 + netdata_mutex_lock(&m->histogram.mutex);
933 +
934 + size_t len = m->histogram.ext->used;
935 + long double *series = m->histogram.ext->values;
936 + sort_series(series, len);
937 +
938 + m->histogram.ext->last_min = (collected_number)roundl(series[0] * 1000.0);
939 + m->histogram.ext->last_max = (collected_number)roundl(series[len - 1] * 1000.0);
940 + m->last = (collected_number)roundl(average(series, len) * 1000);
941 + m->histogram.ext->last_pct = (collected_number)roundl(average(series, (size_t)floor((double)len * statsd.histogram_percentile / 100.0)) * 1000);
942 +
943 + netdata_mutex_unlock(&m->histogram.mutex);
944 + }
945 +
946 + m->reset = 1;
947 + rrddim_set_by_pointer(m->st, m->histogram.ext->rd_min, m->histogram.ext->last_min);
948 + rrddim_set_by_pointer(m->st, m->histogram.ext->rd_max, m->histogram.ext->last_max);
949 + rrddim_set_by_pointer(m->st, m->histogram.ext->rd_pct, m->histogram.ext->last_pct);
950 + rrddim_set_by_pointer(m->st, m->rd_value, m->last);
951 +
952 + if(m->rd_count)
953 + rrddim_set_by_pointer(m->st, m->rd_count, (collected_number)m->events);
954 +
955 + rrdset_done(m->st);
956 +}
957 +
958 +
959 +static inline void statsd_chart_from_timer(STATSD_METRIC *m) {
960 + statsd_chart_from_timer_or_histogram(m, "timer", "timers");
961 +}
962 +
963 +static inline void statsd_chart_from_histogram(STATSD_METRIC *m) {
964 + statsd_chart_from_timer_or_histogram(m, "histogram", "histograms");
965 +}
966 +
967 +static inline void statsd_private_charts_from_index(STATSD_INDEX *index, void (*chart_from_metric)(STATSD_METRIC *)) {
968 STATSD_METRIC *m;
969 for(m = index->first; m ; m = m->next) {
970 if(unlikely(!(m->options & (STATSD_METRIC_OPTION_PRIVATE_CHART_DISABLED|STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED)))) {
@@ -950,6 +1037,17 @@ void *statsd_main(void *ptr) {
1037 statsd.private_charts_memory_mode = rrd_memory_mode_id(config_get(CONFIG_SECTION_STATSD, "private charts memory mode", rrd_memory_mode_name(default_rrd_memory_mode)));
1038 statsd.private_charts_history = (int)config_get_number(CONFIG_SECTION_STATSD, "private charts history", default_rrd_history_entries);
1039
1040 + statsd.histogram_percentile = (double)config_get_float(CONFIG_SECTION_STATSD, "histograms and timers percentile (percentThreshold)", statsd.histogram_percentile);
1041 + if(isless(statsd.histogram_percentile, 0) || isgreater(statsd.histogram_percentile, 100)) {
1042 + error("STATSD: invalid histograms and timers percentile %0.5f given", statsd.histogram_percentile);
1043 + statsd.histogram_percentile = 95.0;
1044 + }
1045 + {
1046 + char buffer[100 + 1];
1047 + snprintf(buffer, 100, "%0.1f%%", statsd.histogram_percentile);
1048 + statsd.histogram_percentile_str = strdupz(buffer);
1049 + }
1050 +
1051 if(config_get_boolean(CONFIG_SECTION_STATSD, "add dimension for number of events received", 1)) {
1052 statsd.gauges.default_options |= STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT;
1053 statsd.counters.default_options |= STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT;
@@ -1069,8 +1167,8 @@ void *statsd_main(void *ptr) {
1167 statsd_private_charts_from_index(&statsd.gauges, statsd_chart_from_gauge);
1168 statsd_private_charts_from_index(&statsd.counters, statsd_chart_from_counter);
1169 statsd_private_charts_from_index(&statsd.meters, statsd_chart_from_meter);
1072 - statsd_private_charts_from_index(&statsd.timers, NULL);
1073 - statsd_private_charts_from_index(&statsd.histograms, NULL);
1170 + statsd_private_charts_from_index(&statsd.timers, statsd_chart_from_timer);
1171 + statsd_private_charts_from_index(&statsd.histograms, statsd_chart_from_histogram);
1172 statsd_private_charts_from_index(&statsd.sets, statsd_chart_from_set);
1173
1174 if(unlikely(netdata_exit))