@cryptotaxi247 / netdata-1 / commits / c10d8c780

added the ability to define the value type on synthetic charts of statsd; fixes #1281

Costa Tsaousis (ktsaou) committed May 12, 2017 at 23:03 UTC c10d8c78089ff702a0187a4fc39835446c1dd4c9
3 files changed +218 -61
conf.d/Makefile.am
+5
@@ -126,3 +126,8 @@ dist_chartsconfig_DATA = \
126 charts.d/postfix.conf \
127 charts.d/squid.conf \
128 $(NULL)
129 +
130 +statsdconfigdir=$(configdir)/statsd.d
131 +dist_statsdconfig_DATA = \
132 + statsd.d/example.conf \
133 + $(NULL)
conf.d/statsd.d/example.conf new
+63
@@ -0,0 +1,63 @@
1 +# statsd synthetic charts configuration
2 +
3 +# You can add many .conf files, one for each of your apps
4 +
5 +# start a new app - you can add many apps in the same file
6 +[app]
7 + # give a name for this app
8 + # this controls the main menu on the dashboard
9 + # and will be the prefix for all charts of the app
10 + name = myapp
11 +
12 + # match all the metrics of the app
13 + metrics = myapp.*
14 +
15 + # shall private charts of these metrics be created?
16 + private charts = no
17 +
18 + # shall gaps be shown when metrics are not collected?
19 + gaps when not collected = no
20 +
21 + # the memory mode for the charts of this app: none|map|save
22 + memory mode = ram
23 +
24 + # the history size for the charts of this app, in seconds
25 + history = 60
26 +
27 +
28 +
29 +# create a chart
30 +# this is its id - the chart will be named myapp.mychart
31 +[mychart]
32 + # a name for the chart, similar to the id (2 names for each chart)
33 + name = mychart
34 +
35 + # the chart title
36 + title = my chart title
37 +
38 + # the submenu of the dashboard
39 + family = my family
40 +
41 + # the context for alarm templates
42 + context = chart.context
43 +
44 + # the units of the chart
45 + units = tests/s
46 +
47 + # the sorting priority of the chart on the dashboard
48 + priority = 91000
49 +
50 + # the type of chart to create: line | area | stacked
51 + type = area
52 +
53 + # one or more dimensions for the chart
54 + # type = events | last | min | max | sum | average | percentile | median | stddev
55 + # events = the number of events for this metric
56 + # last = the last value collected
57 + # all the others are only valid for histograms and timers
58 + dimension = myapp.metric1 avg average 1 1
59 + dimension = myapp.metric1 lower min 1 1
60 + dimension = myapp.metric1 upper max 1 1
61 + dimension = myapp.metric2 other last 1 1
62 +
63 +# You can add as many charts as needed
src/statsd.c
+150 -61
@@ -30,6 +30,7 @@
30 #define STATSD_DICTIONARY_OPTIONS DICTIONARY_FLAG_SINGLE_THREADED
31 #endif
32
33 +#define STATSD_DECIMAL_DETAIL 1000 // floating point values get multiplied by this, with the same divider
34
35 // --------------------------------------------------------------------------------------------------------------------
36 // data specific to each metric type
@@ -43,31 +44,35 @@ typedef struct statsd_metric_counter { // counter and meter
44 } STATSD_METRIC_COUNTER;
45
46 typedef struct statsd_histogram_extensions {
46 - size_t size;
47 - size_t used;
47 + netdata_mutex_t mutex;
48 +
49 + // average is stored in metric->last
50 collected_number last_min;
51 collected_number last_max;
52 collected_number last_percentile;
53 collected_number last_median;
54 collected_number last_stddev;
55 collected_number last_sum;
56 +
57 RRDDIM *rd_min;
58 RRDDIM *rd_max;
59 RRDDIM *rd_percentile;
60 RRDDIM *rd_median;
61 RRDDIM *rd_stddev;
62 RRDDIM *rd_sum;
60 - long double values[]; // dynamic array of values collected
63 +
64 + size_t size;
65 + size_t used;
66 + long double *values; // dynamic array of values collected
67 } STATSD_METRIC_HISTOGRAM_EXTENSIONS;
68
69 typedef struct statsd_metric_histogram { // histogram and timer
64 - netdata_mutex_t mutex;
70 STATSD_METRIC_HISTOGRAM_EXTENSIONS *ext;
71 } STATSD_METRIC_HISTOGRAM;
72
73 typedef struct statsd_metric_set {
74 DICTIONARY *dict;
70 - unsigned long long unique;
75 + size_t unique;
76 } STATSD_METRIC_SET;
77
78
@@ -92,6 +97,7 @@ typedef enum statsd_metric_type {
97 STATSD_METRIC_TYPE_SET
98 } STATSD_METRIC_TYPE;
99
100 +
101 typedef struct statsd_metric {
102 avl avl; // indexing
103
@@ -101,7 +107,7 @@ typedef struct statsd_metric {
107 STATSD_METRIC_TYPE type;
108
109 // metadata about data collection
104 - size_t events; // the number of times this metric has been collected (never resets)
110 + collected_number events; // the number of times this metric has been collected (never resets)
111 size_t count; // the number of times this metric has been collected since the last flush
112
113 // the actual collected data
@@ -146,16 +152,30 @@ static int statsd_metric_compare(void* a, void* b);
152 // --------------------------------------------------------------------------------------------------------------------
153 // synthetic charts
154
155 +typedef enum statsd_app_chart_dimension_value_type {
156 + STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS,
157 + STATSD_APP_CHART_DIM_VALUE_TYPE_LAST,
158 + STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE,
159 + STATSD_APP_CHART_DIM_VALUE_TYPE_SUM,
160 + STATSD_APP_CHART_DIM_VALUE_TYPE_MIN,
161 + STATSD_APP_CHART_DIM_VALUE_TYPE_MAX,
162 + STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE,
163 + STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN,
164 + STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV
165 +} STATSD_APP_CHART_DIM_VALUE_TYPE;
166 +
167 typedef struct statsd_app_chart_dimension {
168 const char *name;
169 const char *metric;
170 uint32_t metric_hash;
171 collected_number multiplier;
172 collected_number divider;
155 - STATSD_INDEX *index;
173 + STATSD_APP_CHART_DIM_VALUE_TYPE value_type;
174
157 - STATSD_METRIC *m;
175 RRDDIM *rd;
176 + collected_number *value_ptr;
177 + RRD_ALGORITHM algorithm;
178 +
179 struct statsd_app_chart_dimension *next;
180 } STATSD_APP_CHART_DIM;
181
@@ -186,7 +206,6 @@ typedef struct statsd_app {
206
207 const char *source;
208 STATSD_APP_CHART *charts;
189 - size_t charts_count;
209 struct statsd_app *next;
210 } STATSD_APP;
211
@@ -334,7 +353,7 @@ static inline STATSD_METRIC *statsd_find_or_add_metric(STATSD_INDEX *index, cons
353
354 if(type == STATSD_METRIC_TYPE_HISTOGRAM || type == STATSD_METRIC_TYPE_TIMER) {
355 m->histogram.ext = callocz(sizeof(STATSD_METRIC_HISTOGRAM_EXTENSIONS), 1);
337 - netdata_mutex_init(&m->histogram.mutex);
356 + netdata_mutex_init(&m->histogram.ext->mutex);
357 }
358 STATSD_METRIC *n = (STATSD_METRIC *)STATSD_AVL_INSERT(&index->index, (avl *)m);
359 if(unlikely(n != m)) {
@@ -443,10 +462,10 @@ static inline void statsd_process_histogram(STATSD_METRIC *m, const char *value,
462 }
463
464 if(unlikely(m->histogram.ext->used == m->histogram.ext->size)) {
446 - netdata_mutex_lock(&m->histogram.mutex);
465 + netdata_mutex_lock(&m->histogram.ext->mutex);
466 m->histogram.ext->size += statsd.histogram_increase_step;
448 - m->histogram.ext = reallocz(m->histogram.ext, sizeof(STATSD_METRIC_HISTOGRAM_EXTENSIONS) + (sizeof(long double) * m->histogram.ext->size));
449 - netdata_mutex_unlock(&m->histogram.mutex);
467 + m->histogram.ext->values = reallocz(m->histogram.ext->values, sizeof(long double) * m->histogram.ext->size);
468 + netdata_mutex_unlock(&m->histogram.ext->mutex);
469 }
470
471 m->histogram.ext->values[m->histogram.ext->used++] = statsd_parse_float(value, 1.0) / statsd_parse_float(sampling, 1.0);
@@ -1082,14 +1101,15 @@ int statsd_readfile(const char *path, const char *filename) {
1101 chart->chart_type = rrdset_type_id(value);
1102 }
1103 else if (!strcmp(name, "dimension")) {
1085 - // metric [name [multiplier [divider]]]
1086 - char *words[4];
1087 - pluginsd_split_words(value, words, 4);
1104 + // metric [name [type [multiplier [divider]]]]
1105 + char *words[5];
1106 + pluginsd_split_words(value, words, 5);
1107
1108 char *metric_name = words[0];
1109 char *dim_name = words[1];
1091 - char *multipler = words[2];
1092 - char *divider = words[3];
1110 + char *type = words[2];
1111 + char *multipler = words[3];
1112 + char *divider = words[4];
1113
1114 STATSD_APP_CHART_DIM *dim = callocz(sizeof(STATSD_APP_CHART_DIM), 1);
1115 dim->next = chart->dimensions;
@@ -1103,6 +1123,21 @@ int statsd_readfile(const char *path, const char *filename) {
1123 dim->multiplier = (multipler && *multipler)?str2l(multipler):1;
1124 dim->divider = (divider && *divider)?str2l(divider):1;
1125
1126 + if(!type || !*type) type = "last";
1127 + if(!strcmp(type, "events")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS;
1128 + else if(!strcmp(type, "last")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_LAST;
1129 + else if(!strcmp(type, "min")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_MIN;
1130 + else if(!strcmp(type, "max")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_MAX;
1131 + else if(!strcmp(type, "sum")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_SUM;
1132 + else if(!strcmp(type, "average")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE;
1133 + else if(!strcmp(type, "median")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN;
1134 + else if(!strcmp(type, "stddev")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV;
1135 + else if(!strcmp(type, "percentile")) dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE;
1136 + else {
1137 + error("STATSD: invalid type '%s' at line %zu of file '%s/%s'. Using 'last'.", type, line, path, filename);
1138 + dim->value_type = STATSD_APP_CHART_DIM_VALUE_TYPE_LAST;
1139 + }
1140 +
1141 if(!dim->multiplier) {
1142 error("STATSD: invalid multiplier value '%s' at line %zu of file '%s/%s'. Using 1.", multipler, line, path, filename);
1143 dim->multiplier = 1;
@@ -1253,7 +1288,7 @@ static inline void statsd_private_chart_gauge(STATSD_METRIC *m) {
1288 , RRDSET_TYPE_LINE
1289 );
1290
1256 - m->rd_value = rrddim_add(m->st, "gauge", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1291 + m->rd_value = rrddim_add(m->st, "gauge", NULL, 1, STATSD_DECIMAL_DETAIL, RRD_ALGORITHM_ABSOLUTE);
1292
1293 if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT)
1294 m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
@@ -1263,7 +1298,7 @@ static inline void statsd_private_chart_gauge(STATSD_METRIC *m) {
1298 rrddim_set_by_pointer(m->st, m->rd_value, m->last);
1299
1300 if(m->rd_count)
1266 - rrddim_set_by_pointer(m->st, m->rd_count, (collected_number)m->events);
1301 + rrddim_set_by_pointer(m->st, m->rd_count, m->events);
1302
1303 rrdset_done(m->st);
1304 }
@@ -1299,7 +1334,7 @@ static inline void statsd_private_chart_counter_or_meter(STATSD_METRIC *m, const
1334 rrddim_set_by_pointer(m->st, m->rd_value, m->last);
1335
1336 if(m->rd_count)
1302 - rrddim_set_by_pointer(m->st, m->rd_count, (collected_number)m->events);
1337 + rrddim_set_by_pointer(m->st, m->rd_count, m->events);
1338
1339 rrdset_done(m->st);
1340 }
@@ -1335,7 +1370,7 @@ static inline void statsd_private_chart_set(STATSD_METRIC *m) {
1370 rrddim_set_by_pointer(m->st, m->rd_value, m->last);
1371
1372 if(m->rd_count)
1338 - rrddim_set_by_pointer(m->st, m->rd_count, (collected_number)m->events);
1373 + rrddim_set_by_pointer(m->st, m->rd_count, m->events);
1374
1375 rrdset_done(m->st);
1376 }
@@ -1361,13 +1396,13 @@ static inline void statsd_private_chart_timer_or_histogram(STATSD_METRIC *m, con
1396 , RRDSET_TYPE_AREA
1397 );
1398
1364 - m->histogram.ext->rd_min = rrddim_add(m->st, "min", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1365 - m->histogram.ext->rd_max = rrddim_add(m->st, "max", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1366 - m->rd_value = rrddim_add(m->st, "average", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1367 - m->histogram.ext->rd_percentile = rrddim_add(m->st, statsd.histogram_percentile_str, NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1368 - m->histogram.ext->rd_median = rrddim_add(m->st, "median", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1369 - m->histogram.ext->rd_stddev = rrddim_add(m->st, "stddev", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1370 - m->histogram.ext->rd_sum = rrddim_add(m->st, "sum", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
1399 + m->histogram.ext->rd_min = rrddim_add(m->st, "min", NULL, 1, STATSD_DECIMAL_DETAIL, RRD_ALGORITHM_ABSOLUTE);
1400 + m->histogram.ext->rd_max = rrddim_add(m->st, "max", NULL, 1, STATSD_DECIMAL_DETAIL, RRD_ALGORITHM_ABSOLUTE);
1401 + m->rd_value = rrddim_add(m->st, "average", NULL, 1, STATSD_DECIMAL_DETAIL, RRD_ALGORITHM_ABSOLUTE);
1402 + m->histogram.ext->rd_percentile = rrddim_add(m->st, statsd.histogram_percentile_str, NULL, 1, STATSD_DECIMAL_DETAIL, RRD_ALGORITHM_ABSOLUTE);
1403 + m->histogram.ext->rd_median = rrddim_add(m->st, "median", NULL, 1, STATSD_DECIMAL_DETAIL, RRD_ALGORITHM_ABSOLUTE);
1404 + m->histogram.ext->rd_stddev = rrddim_add(m->st, "stddev", NULL, 1, STATSD_DECIMAL_DETAIL, RRD_ALGORITHM_ABSOLUTE);
1405 + m->histogram.ext->rd_sum = rrddim_add(m->st, "sum", NULL, 1, STATSD_DECIMAL_DETAIL, RRD_ALGORITHM_ABSOLUTE);
1406
1407 if(m->options & STATSD_METRIC_OPTION_CHART_DIMENSION_COUNT)
1408 m->rd_count = rrddim_add(m->st, "events", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
@@ -1383,7 +1418,7 @@ static inline void statsd_private_chart_timer_or_histogram(STATSD_METRIC *m, con
1418 rrddim_set_by_pointer(m->st, m->rd_value, m->last);
1419
1420 if(m->rd_count)
1386 - rrddim_set_by_pointer(m->st, m->rd_count, (collected_number)m->events);
1421 + rrddim_set_by_pointer(m->st, m->rd_count, m->events);
1422
1423 rrdset_done(m->st);
1424 }
@@ -1396,7 +1431,7 @@ static inline void statsd_flush_gauge(STATSD_METRIC *m) {
1431
1432 int updated = 0;
1433 if(m->count && !m->reset) {
1399 - m->last = (collected_number) (m->gauge.value * 1000.0);
1434 + m->last = (collected_number) (m->gauge.value * STATSD_DECIMAL_DETAIL);
1435
1436 m->reset = 1;
1437 updated = 1;
@@ -1434,7 +1469,7 @@ static inline void statsd_flush_set(STATSD_METRIC *m) {
1469
1470 int updated = 0;
1471 if(m->count && !m->reset) {
1437 - m->last = m->set.unique;
1472 + m->last = (collected_number)m->set.unique;
1473
1474 m->reset = 1;
1475 updated = 1;
@@ -1447,7 +1482,7 @@ static inline void statsd_flush_set(STATSD_METRIC *m) {
1482 static inline void statsd_flush_timer_or_histogram(STATSD_METRIC *m, const char *dim, const char *family, const char *units) {
1483 debug(D_STATSD, "flushing %s metric '%s'", dim, m->name);
1484
1450 - netdata_mutex_lock(&m->histogram.mutex);
1485 + netdata_mutex_lock(&m->histogram.ext->mutex);
1486
1487 int updated = 0;
1488 if(m->count && !m->reset) {
@@ -1455,13 +1490,13 @@ static inline void statsd_flush_timer_or_histogram(STATSD_METRIC *m, const char
1490 long double *series = m->histogram.ext->values;
1491 sort_series(series, len);
1492
1458 - m->histogram.ext->last_min = (collected_number)roundl(series[0] * 1000);
1459 - m->histogram.ext->last_max = (collected_number)roundl(series[len - 1] * 1000);
1460 - m->last = (collected_number)roundl(average(series, len) * 1000);
1461 - m->histogram.ext->last_percentile = (collected_number)roundl(average(series, (size_t)floor((double)len * statsd.histogram_percentile / 100.0)) * 1000);
1462 - m->histogram.ext->last_median = (collected_number)roundl(median_on_sorted_series(series, len) * 1000);
1463 - m->histogram.ext->last_stddev = (collected_number)roundl(standard_deviation(series, len) * 1000);
1464 - m->histogram.ext->last_sum = (collected_number)roundl(sum(series, len) * 1000);
1493 + m->histogram.ext->last_min = (collected_number)roundl(series[0] * STATSD_DECIMAL_DETAIL);
1494 + m->histogram.ext->last_max = (collected_number)roundl(series[len - 1] * STATSD_DECIMAL_DETAIL);
1495 + m->last = (collected_number)roundl(average(series, len) * STATSD_DECIMAL_DETAIL);
1496 + m->histogram.ext->last_percentile = (collected_number)roundl(average(series, (size_t)floor((double)len * statsd.histogram_percentile / 100.0)) * STATSD_DECIMAL_DETAIL);
1497 + m->histogram.ext->last_median = (collected_number)roundl(median_on_sorted_series(series, len) * STATSD_DECIMAL_DETAIL);
1498 + m->histogram.ext->last_stddev = (collected_number)roundl(standard_deviation(series, len) * STATSD_DECIMAL_DETAIL);
1499 + m->histogram.ext->last_sum = (collected_number)roundl(sum(series, len) * STATSD_DECIMAL_DETAIL);
1500
1501 m->reset = 1;
1502 updated = 1;
@@ -1471,7 +1506,7 @@ static inline void statsd_flush_timer_or_histogram(STATSD_METRIC *m, const char
1506 if(m->options & STATSD_METRIC_OPTION_PRIVATE_CHART_ENABLED && (updated || !(m->options & STATSD_METRIC_OPTION_SHOW_GAPS_WHEN_NOT_COLLECTED)))
1507 statsd_private_chart_timer_or_histogram(m, dim, family, units);
1508
1474 - netdata_mutex_unlock(&m->histogram.mutex);
1509 + netdata_mutex_unlock(&m->histogram.ext->mutex);
1510 }
1511
1512 static inline void statsd_flush_timer(STATSD_METRIC *m) {
@@ -1482,6 +1517,21 @@ static inline void statsd_flush_histogram(STATSD_METRIC *m) {
1517 statsd_flush_timer_or_histogram(m, "histogram", "histograms", "value");
1518 }
1519
1520 +static inline RRD_ALGORITHM statsd_algorithm_for_metric(STATSD_METRIC *m) {
1521 + switch(m->type) {
1522 + default:
1523 + case STATSD_METRIC_TYPE_GAUGE:
1524 + case STATSD_METRIC_TYPE_SET:
1525 + case STATSD_METRIC_TYPE_TIMER:
1526 + case STATSD_METRIC_TYPE_HISTOGRAM:
1527 + return RRD_ALGORITHM_ABSOLUTE;
1528 +
1529 + case STATSD_METRIC_TYPE_METER:
1530 + case STATSD_METRIC_TYPE_COUNTER:
1531 + return RRD_ALGORITHM_INCREMENTAL;
1532 + }
1533 +}
1534 +
1535 static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC *m) {
1536 (void)index;
1537
@@ -1509,10 +1559,64 @@ static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC
1559 for(chart = app->charts; chart; chart = chart->next) {
1560 STATSD_APP_CHART_DIM *dim;
1561 for(dim = chart->dimensions; dim ; dim = dim->next) {
1512 - if(!dim->m && dim->metric_hash == m->hash && !strcmp(dim->metric, m->name)) {
1562 + if(!dim->value_ptr && dim->metric_hash == m->hash && !strcmp(dim->metric, m->name)) {
1563 // we have a match - this metric should be linked to this dimension
1564 debug(D_STATSD, "metric '%s' linked with app '%s', chart '%s', dimension '%s'", m->name, app->name, chart->id, dim->name);
1515 - dim->m = m;
1565 +
1566 + if(dim->value_type == STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS) {
1567 + dim->value_ptr = &m->events;
1568 + dim->algorithm = RRD_ALGORITHM_INCREMENTAL;
1569 + }
1570 + else if(m->type == STATSD_METRIC_TYPE_HISTOGRAM || m->type == STATSD_METRIC_TYPE_TIMER) {
1571 + dim->algorithm = RRD_ALGORITHM_ABSOLUTE;
1572 + dim->divider *= STATSD_DECIMAL_DETAIL;
1573 +
1574 + switch(dim->value_type) {
1575 + case STATSD_APP_CHART_DIM_VALUE_TYPE_EVENTS:
1576 + // will never match - added to avoid warning
1577 + break;
1578 +
1579 + case STATSD_APP_CHART_DIM_VALUE_TYPE_LAST:
1580 + case STATSD_APP_CHART_DIM_VALUE_TYPE_AVERAGE:
1581 + dim->value_ptr = &m->last;
1582 + break;
1583 +
1584 + case STATSD_APP_CHART_DIM_VALUE_TYPE_SUM:
1585 + dim->value_ptr = &m->histogram.ext->last_sum;
1586 + break;
1587 +
1588 + case STATSD_APP_CHART_DIM_VALUE_TYPE_MIN:
1589 + dim->value_ptr = &m->histogram.ext->last_min;
1590 + break;
1591 +
1592 + case STATSD_APP_CHART_DIM_VALUE_TYPE_MAX:
1593 + dim->value_ptr = &m->histogram.ext->last_max;
1594 + break;
1595 +
1596 + case STATSD_APP_CHART_DIM_VALUE_TYPE_MEDIAN:
1597 + dim->value_ptr = &m->histogram.ext->last_median;
1598 + break;
1599 +
1600 + case STATSD_APP_CHART_DIM_VALUE_TYPE_PERCENTILE:
1601 + dim->value_ptr = &m->histogram.ext->last_percentile;
1602 + break;
1603 +
1604 + case STATSD_APP_CHART_DIM_VALUE_TYPE_STDDEV:
1605 + dim->value_ptr = &m->histogram.ext->last_stddev;
1606 + break;
1607 + }
1608 + }
1609 + else {
1610 + if (dim->value_type != STATSD_APP_CHART_DIM_VALUE_TYPE_LAST)
1611 + error("STATSD: unsupported value type for dimension '%s' of chart '%s' of app '%s' on metric '%s'", dim->name, chart->name, app->name, m->name);
1612 +
1613 + dim->value_ptr = &m->last;
1614 + dim->algorithm = statsd_algorithm_for_metric(m);
1615 +
1616 + if(m->type == STATSD_METRIC_TYPE_GAUGE)
1617 + dim->divider *= STATSD_DECIMAL_DETAIL;
1618 + }
1619 +
1620 chart->dimensions_linked_count++;
1621 }
1622 }
@@ -1521,21 +1625,6 @@ static inline void check_if_metric_is_for_app(STATSD_INDEX *index, STATSD_METRIC
1625 }
1626 }
1627
1524 -static inline RRD_ALGORITHM statsd_algorithm_for_metric(STATSD_METRIC *m) {
1525 - switch(m->type) {
1526 - default:
1527 - case STATSD_METRIC_TYPE_GAUGE:
1528 - case STATSD_METRIC_TYPE_SET:
1529 - case STATSD_METRIC_TYPE_TIMER:
1530 - case STATSD_METRIC_TYPE_HISTOGRAM:
1531 - return RRD_ALGORITHM_ABSOLUTE;
1532 -
1533 - case STATSD_METRIC_TYPE_METER:
1534 - case STATSD_METRIC_TYPE_COUNTER:
1535 - return RRD_ALGORITHM_INCREMENTAL;
1536 - }
1537 -}
1538 -
1628 static inline void statsd_update_app_chart(STATSD_APP *app, STATSD_APP_CHART *chart) {
1629 debug(D_STATSD, "updating chart '%s' for app '%s'", chart->id, app->name);
1630
@@ -1560,11 +1649,11 @@ static inline void statsd_update_app_chart(STATSD_APP *app, STATSD_APP_CHART *ch
1649
1650 STATSD_APP_CHART_DIM *dim;
1651 for(dim = chart->dimensions; dim ;dim = dim->next) {
1563 - if(dim->m) {
1652 + if(dim->value_ptr) {
1653 if(unlikely(!dim->rd))
1565 - dim->rd = rrddim_add(chart->st, dim->metric, dim->name, dim->multiplier, dim->divider,statsd_algorithm_for_metric(dim->m));
1654 + dim->rd = rrddim_add(chart->st, dim->metric, dim->name, dim->multiplier, dim->divider, dim->algorithm);
1655
1567 - rrddim_set_by_pointer(chart->st, dim->rd, dim->m->last);
1656 + rrddim_set_by_pointer(chart->st, dim->rd, *dim->value_ptr);
1657 }
1658 }
1659