@cryptotaxi247 / netdata-1 / commits / b8dfb4cea

statsd now tracks useful metrics and loops through them only

Costa Tsaousis (ktsaou) committed Apr 17, 2018 at 01:16 UTC b8dfb4cea9de9dcf2d4841d6072f4734f8957226
1 file changed +42 -18
src/statsd.c
+42 -18
@@ -87,7 +87,8 @@ typedef enum statsd_metric_options {
87 STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED = 0x00000002, // render a private chart for this metric
88 STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED = 0x00000004, // the metric has been checked if it should get private chart or not
89 STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT = 0x00000008, // show the count of events for this private chart
90 - STATSD_METRIC_OPTION_CHECKED_IN_APPS = 0x00000010, // set when this metric has been checked agains apps
90 + STATSD_METRIC_OPTION_CHECKED_IN_APPS = 0x00000010, // set when this metric has been checked against apps
91 + STATSD_METRIC_OPTION_USED_IN_APPS = 0x00000020, // set when this metric is used in apps
92 } STATS_METRIC_OPTIONS;
93
94 typedef enum statsd_metric_type {
@@ -130,6 +131,7 @@ typedef struct statsd_metric {
131
132 // linking, used for walking through all metrics
133 struct statsd_metric *next;
134 + struct statsd_metric *next_useful;
135 } STATSD_METRIC;
136
137
@@ -144,6 +146,7 @@ typedef struct statsd_index {
146 STATSD_AVL_TREE index; // the AVL tree
147
148 STATSD_METRIC *first; // the linked list of metrics (new metrics are added in front)
149 + STATSD_METRIC *first_useful; // the linked list of useful metrics (new metrics are added in front)
150 STATSD_FIRST_PTR_MUTEX; // when mutli-threading is enabled, a lock to protect the linked list
151
152 STATS_METRIC_OPTIONS default_options; // default options for all metrics in this index
@@ -455,7 +458,17 @@ static inline int value_is_zinit(const char *value) {
458 return (value && *value == 'z' && *++value == 'i' && *++value == 'n' && *++value == 'i' && *++value == 't' && *++value == '\0');
459 }
460
461 +static inline int is_metric_checked(STATSD_METRIC *m) {
462 + return ((m->options & (STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED|STATSD_METRIC_OPTION_CHECKED_IN_APPS)) == (STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED|STATSD_METRIC_OPTION_CHECKED_IN_APPS));
463 +}
464 +
465 +static inline int is_metric_useful(STATSD_METRIC *m) {
466 + return (!is_metric_checked(m) || (m->options & (STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED|STATSD_METRIC_OPTION_USED_IN_APPS)) != 0);
467 +}
468 +
469 static inline void statsd_process_gauge(STATSD_METRIC *m, const char *value, const char *sampling) {
470 + if(!is_metric_useful(m)) return;
471 +
472 if(unlikely(!value || !*value)) {
473 error("STATSD: metric '%s' of type gauge, with empty value is ignored.", m->name);
474 return;
@@ -480,7 +493,9 @@ static inline void statsd_process_gauge(STATSD_METRIC *m, const char *value, con
493 }
494 }
495
483 -static inline void statsd_process_counter(STATSD_METRIC *m, const char *value, const char *sampling) {
496 +static inline void statsd_process_counter_or_meter(STATSD_METRIC *m, const char *value, const char *sampling) {
497 + if(!is_metric_useful(m)) return;
498 +
499 // we accept empty values for counters
500
501 if(unlikely(m->reset)) statsd_reset_metric(m);
@@ -496,14 +511,14 @@ static inline void statsd_process_counter(STATSD_METRIC *m, const char *value, c
511 }
512 }
513
499 -static inline void statsd_process_meter(STATSD_METRIC *m, const char *value, const char *sampling) {
500 - // this is the same with the counter
501 - statsd_process_counter(m, value, sampling);
502 -}
514 +#define statsd_process_counter(m, value, sampling) statsd_process_counter_or_meter(m, value, sampling)
515 +#define statsd_process_meter(m, value, sampling) statsd_process_counter_or_meter(m, value, sampling)
516 +
517 +static inline void statsd_process_histogram_or_timer(STATSD_METRIC *m, const char *value, const char *sampling, const char *type) {
518 + if(!is_metric_useful(m)) return;
519
504 -static inline void statsd_process_histogram(STATSD_METRIC *m, const char *value, const char *sampling) {
520 if(unlikely(!value || !*value)) {
506 - error("STATSD: metric '%s' of type histogram, with empty value is ignored.", m->name);
521 + error("STATSD: metric of type %s, with empty value is ignored.", type);
522 return;
523 }
524
@@ -530,17 +545,12 @@ static inline void statsd_process_histogram(STATSD_METRIC *m, const char *value,
545 }
546 }
547
533 -static inline void statsd_process_timer(STATSD_METRIC *m, const char *value, const char *sampling) {
534 - if(unlikely(!value || !*value)) {
535 - error("STATSD: metric of type timer, with empty value is ignored.");
536 - return;
537 - }
538 -
539 - // timers are a use case of histogram
540 - statsd_process_histogram(m, value, sampling);
541 -}
548 +#define statsd_process_timer(m, value, sampling) statsd_process_histogram_or_timer(m, value, sampling, "timer")
549 +#define statsd_process_histogram(m, value, sampling) statsd_process_histogram_or_timer(m, value, sampling, "histogram")
550
551 static inline void statsd_process_set(STATSD_METRIC *m, const char *value) {
552 + if(!is_metric_useful(m)) return;
553 +
554 if(unlikely(!value || !*value)) {
555 error("STATSD: metric of type set, with empty value is ignored.");
556 return;
@@ -1839,6 +1849,7 @@ static inline void link_metric_to_app_dimension(STATSD_APP *app, STATSD_METRIC *
1849 }
1850
1851 chart->dimensions_linked_count++;
1852 + m->options |= STATSD_METRIC_OPTION_USED_IN_APPS;
1853 debug(D_STATSD, "metric '%s' of type %u linked with app '%s', chart '%s', dimension '%s', algorithm '%s'", m->name, m->type, app->name, chart->id, dim->name, rrd_algorithm_name(dim->algorithm));
1854 }
1855
@@ -2045,7 +2056,13 @@ const char *statsd_metric_type_string(STATSD_METRIC_TYPE type) {
2056
2057 static inline void statsd_flush_index_metrics(STATSD_INDEX *index, void (*flush_metric)(STATSD_METRIC *)) {
2058 STATSD_METRIC *m;
2059 +
2060 + // find the useful metrics (incremental = each time we are called, we check the new metrics only)
2061 for(m = index->first; m ; m = m->next) {
2062 + // since we add new metrics at the beginning
2063 + // check for useful charts, until the point we last checked
2064 + if(unlikely(is_metric_checked(m))) break;
2065 +
2066 if(unlikely(!(m->options & STATSD_METRIC_OPTION_CHECKED_IN_APPS))) {
2067 log_access("NEW STATSD METRIC '%s': '%s'", statsd_metric_type_string(m->type), m->name);
2068 check_if_metric_is_for_app(index, m);
@@ -2071,8 +2088,15 @@ static inline void statsd_flush_index_metrics(STATSD_INDEX *index, void (*flush_
2088 m->options |= STATSD_METRIC_OPTION_PRIVATE_CHART_CHECKED;
2089 }
2090
2074 - flush_metric(m);
2091 + if(is_metric_useful(m)) {
2092 + m->next_useful = index->first_useful;
2093 + index->first_useful = m;
2094 + }
2095 }
2096 +
2097 + // flush all the useful metrics
2098 + for(m = index->first_useful; m ; m = m->next_useful)
2099 + flush_metric(m);
2100 }
2101
2102