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