// SPDX-License-Identifier: GPL-3.0-or-later
#include "daemon/common.h"
#include "KolmogorovSmirnovDist.h"
#define MAX_POINTS 10000
int enable_metric_correlations = CONFIG_BOOLEAN_YES;
int metric_correlations_version = 1;
METRIC_CORRELATIONS_METHOD default_metric_correlations_method = METRIC_CORRELATIONS_KS2;
typedef struct mc_stats {
NETDATA_DOUBLE max_base_high_ratio;
size_t db_points;
size_t result_points;
size_t db_queries;
size_t binary_searches;
} MC_STATS;
// ----------------------------------------------------------------------------
// parse and render metric correlations methods
static struct {
const char *name;
METRIC_CORRELATIONS_METHOD value;
} metric_correlations_methods[] = {
{ "ks2" , METRIC_CORRELATIONS_KS2 }
, { "volume" , METRIC_CORRELATIONS_VOLUME }
, { NULL , 0 }
};
METRIC_CORRELATIONS_METHOD mc_string_to_method(const char *method) {
for(int i = 0; metric_correlations_methods[i].name ;i++)
if(strcmp(method, metric_correlations_methods[i].name) == 0)
return metric_correlations_methods[i].value;
return default_metric_correlations_method;
}
const char *mc_method_to_string(METRIC_CORRELATIONS_METHOD method) {
for(int i = 0; metric_correlations_methods[i].name ;i++)
if(metric_correlations_methods[i].value == method)
return metric_correlations_methods[i].name;
return "unknown";
}
// ----------------------------------------------------------------------------
// The results per dimension are aggregated into a dictionary
typedef enum {
RESULT_IS_BASE_HIGH_RATIO = (1 << 0),
RESULT_IS_PERCENTAGE_OF_TIME = (1 << 1),
} RESULT_FLAGS;
struct register_result {
RESULT_FLAGS flags;
RRDSET *st;
const char *chart_id;
const char *context;
const char *dim_name;
NETDATA_DOUBLE value;
};
static void register_result_insert_callback(const char *name, void *value, void *data) {
(void)name;
(void)data;
struct register_result *t = (struct register_result *)value;
if(t->chart_id) t->chart_id = strdupz(t->chart_id);
if(t->context) t->context = strdupz(t->context);
if(t->dim_name) t->dim_name = strdupz(t->dim_name);
}
static void register_result_delete_callback(const char *name, void *value, void *data) {
(void)name;
(void)data;
struct register_result *t = (struct register_result *)value;
freez((void *)t->chart_id);
freez((void *)t->context);
freez((void *)t->dim_name);
}
static DICTIONARY *register_result_init() {
DICTIONARY *results = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
dictionary_register_insert_callback(results, register_result_insert_callback, results);
dictionary_register_delete_callback(results, register_result_delete_callback, results);
return results;
}
static void register_result_destroy(DICTIONARY *results) {
dictionary_destroy(results);
}
static void register_result(DICTIONARY *results, RRDSET *st, RRDDIM *d, NETDATA_DOUBLE value, RESULT_FLAGS flags, MC_STATS *stats) {
if(!netdata_double_isnumber(value)) return;
// make it positive
NETDATA_DOUBLE v = fabsndd(value);
// no need to store zero scored values
if(v == 0.0) return;
// keep track of the max of the baseline / highlight ratio
if(flags & RESULT_IS_BASE_HIGH_RATIO && v > stats->max_base_high_ratio