#include "stats-settings.h"
#include "array.h"
+/* <settings checks> */
+#include <math.h>
+/* </settings checks> */
+
static bool stats_metric_settings_check(void *_set, pool_t pool, const char **error_r);
static bool stats_exporter_settings_check(void *_set, pool_t pool, const char **error_r);
static bool stats_settings_check(void *_set, pool_t pool, const char **error_r);
return TRUE;
}
+static bool parse_metric_group_by_exp(pool_t pool, struct stats_metric_settings_group_by *group_by,
+ const char *const *params, const char **error_r)
+{
+ intmax_t min, max, base;
+
+ if (!parse_metric_group_by_common("exponential", params, &min, &max, &base, error_r))
+ return FALSE;
+
+ if ((base != 2) && (base != 10)) {
+ *error_r = t_strdup_printf("group_by 'exponential' aggregate function "
+ "base must be one of: 2, 10 (base=%ju)",
+ base);
+ return FALSE;
+ }
+
+ group_by->func = STATS_METRIC_GROUPBY_QUANTIZED;
+
+ /*
+ * Allocate the bucket range array and fill it in
+ *
+ * The first bucket is special - it contains everything less than or
+ * equal to 'base^min'. The last bucket is also special - it
+ * contains everything greater than 'base^max'.
+ *
+ * The second bucket begins at 'base^min + 1', the third bucket
+ * begins at 'base^(min + 1) + 1', and so on.
+ */
+ group_by->num_ranges = max - min + 2;
+ group_by->ranges = p_new(pool, struct stats_metric_settings_bucket_range,
+ group_by->num_ranges);
+
+ /* set up min & max buckets */
+ group_by->ranges[0].min = INTMAX_MIN;
+ group_by->ranges[0].max = pow(base, min);
+ group_by->ranges[group_by->num_ranges - 1].min = pow(base, max);
+ group_by->ranges[group_by->num_ranges - 1].max = INTMAX_MAX;
+
+ /* remaining buckets */
+ for (unsigned int i = 1; i < group_by->num_ranges - 1; i++) {
+ group_by->ranges[i].min = pow(base, min + (i - 1));
+ group_by->ranges[i].max = pow(base, min + i);
+ }
+
+ return TRUE;
+}
+
static bool parse_metric_group_by_lin(pool_t pool, struct stats_metric_settings_group_by *group_by,
const char *const *params, const char **error_r)
{
"does not take any args";
return FALSE;
}
+ } else if (strcmp(params[1], "exponential") == 0) {
+ /* <field>:exponential:<min mag>:<max mag>:<base> */
+ if (!parse_metric_group_by_exp(pool, &group_by, ¶ms[2], error_r))
+ return FALSE;
} else if (strcmp(params[1], "linear") == 0) {
/* <field>:linear:<min val>:<max val>:<step> */
if (!parse_metric_group_by_lin(pool, &group_by, ¶ms[2], error_r))
{ { 1000, INTMAX_MAX }, 2 },
}
},
+ {
+ /* start at 0 */
+ "exponential:0:6:10",
+ 12,
+ { 0, 5, 10, 11, 100, 101, 500, 1000, 1001, 1000000, 1000001, 2000000 },
+ 7,
+ 8,
+ { { { INTMAX_MIN, 1 }, 1 },
+ { { 1, 10 }, 2 },
+ { { 10, 100 }, 2 },
+ { { 100, 1000 }, 3 },
+ { { 1000, 10000 }, 1 },
+ { { 10000, 100000 }, 0 },
+ { { 100000, 1000000 }, 1 },
+ { { 1000000, INTMAX_MAX }, 2 },
+ }
+ },
+ {
+ /* start at 0 */
+ "exponential:0:6:2",
+ 9,
+ { 0, 1, 2, 4, 5, 20, 64, 65, 100 },
+ 7,
+ 8,
+ { { { INTMAX_MIN, 1 }, 2 },
+ { { 1, 2 }, 1 },
+ { { 2, 4 }, 1 },
+ { { 4, 8 }, 1 },
+ { { 8, 16 }, 0 },
+ { { 16, 32 }, 1 },
+ { { 32, 64 }, 1 },
+ { { 64, INTMAX_MAX }, 2 },
+ }
+ },
+ {
+ /* start at >0 */
+ "exponential:2:6:10",
+ 12,
+ { 0, 5, 10, 11, 100, 101, 500, 1000, 1001, 1000000, 1000001, 2000000 },
+ 5,
+ 6,
+ { { { INTMAX_MIN, 100 }, 5 },
+ { { 100, 1000 }, 3 },
+ { { 1000, 10000 }, 1 },
+ { { 10000, 100000 }, 0 },
+ { { 100000, 1000000 }, 1 },
+ { { 1000000, INTMAX_MAX }, 2 },
+ }
+ },
+ {
+ /* start at >0 */
+ "exponential:2:6:2",
+ 9,
+ { 0, 1, 2, 4, 5, 20, 64, 65, 100 },
+ 5,
+ 6,
+ { { { INTMAX_MIN, 4 }, 4 },
+ { { 4, 8 }, 1 },
+ { { 8, 16 }, 0 },
+ { { 16, 32 }, 1 },
+ { { 32, 64 }, 1 },
+ { { 64, INTMAX_MAX }, 2 },
+ }
+ },
};
static void test_stats_metrics_group_by_quantized_real(const struct quantized_test *test)