From 6f593432a4d06c53e909d2fa80f33d2fbe210eb5 Mon Sep 17 00:00:00 2001 From: Gaber Stare Date: Mon, 6 Mar 2023 11:44:30 +0000 Subject: [PATCH] [AMF metrics] Initial histogram support Version of histogram support without ogs_metrics_spec_new_ex(). Buckets are now, just like labels, passed to ogs_metrics_spec_new() as a pointer. --- lib/metrics/context.h | 29 +++++++++++++++++- lib/metrics/prometheus/context.c | 50 +++++++++++++++++++++++++++++++- lib/metrics/void/context.c | 3 +- src/amf/metrics.c | 17 ++++++++++- src/amf/metrics.h | 1 + src/mme/metrics.c | 3 +- src/pcf/metrics.c | 3 +- src/smf/metrics.c | 3 +- src/upf/metrics.c | 3 +- 9 files changed, 104 insertions(+), 8 deletions(-) diff --git a/lib/metrics/context.h b/lib/metrics/context.h index fdc9ec3cf..5b1a92039 100644 --- a/lib/metrics/context.h +++ b/lib/metrics/context.h @@ -33,6 +33,7 @@ typedef struct ogs_metrics_server_s ogs_metrics_server_t; typedef enum ogs_metrics_metric_type_s { OGS_METRICS_METRIC_TYPE_COUNTER, OGS_METRICS_METRIC_TYPE_GAUGE, + OGS_METRICS_METRIC_TYPE_HISTOGRAM, } ogs_metrics_metric_type_t; typedef struct ogs_metrics_context_s { @@ -42,6 +43,31 @@ typedef struct ogs_metrics_context_s { uint16_t metrics_port; } ogs_metrics_context_t; +typedef enum ogs_metrics_histogram_bucket_type_s { + OGS_METRICS_HISTOGRAM_BUCKET_TYPE_VARIABLE, + OGS_METRICS_HISTOGRAM_BUCKET_TYPE_LINEAR, + OGS_METRICS_HISTOGRAM_BUCKET_TYPE_EXPONENTIAL, +} ogs_metrics_histogram_bucket_type_t; + +typedef struct ogs_metrics_histogram_bucket_params_s { + ogs_metrics_histogram_bucket_type_t type; + unsigned int count; +#define OGS_METRICS_HIST_VAR_BUCKETS_MAX 10 + union { + struct { + float start; + float width; + } lin; + struct { + float start; + float factor; + } exp; + struct { + float buckets[OGS_METRICS_HIST_VAR_BUCKETS_MAX]; + } var; + }; +} ogs_metrics_histogram_params_t; + typedef struct ogs_metrics_context_s ogs_metrics_context_t; void ogs_metrics_context_init(void); void ogs_metrics_context_open(ogs_metrics_context_t *ctx); @@ -65,7 +91,8 @@ void ogs_metrics_spec_final(ogs_metrics_context_t *ctx); ogs_metrics_spec_t *ogs_metrics_spec_new( ogs_metrics_context_t *ctx, ogs_metrics_metric_type_t type, const char *name, const char *description, - int initial_val, unsigned int num_labels, const char **labels); + int initial_val, unsigned int num_labels, const char ** labels, + ogs_metrics_histogram_params_t *histogram_params); void ogs_metrics_spec_free(ogs_metrics_spec_t *spec); typedef struct ogs_metrics_inst_s ogs_metrics_inst_t; diff --git a/lib/metrics/prometheus/context.c b/lib/metrics/prometheus/context.c index 59dd30d8c..6220df230 100644 --- a/lib/metrics/prometheus/context.c +++ b/lib/metrics/prometheus/context.c @@ -339,7 +339,8 @@ void ogs_metrics_spec_final(ogs_metrics_context_t *ctx) ogs_metrics_spec_t *ogs_metrics_spec_new( ogs_metrics_context_t *ctx, ogs_metrics_metric_type_t type, const char *name, const char *description, - int initial_val, unsigned int num_labels, const char ** labels) + int initial_val, unsigned int num_labels, const char ** labels, + ogs_metrics_histogram_params_t *histogram_params) { ogs_metrics_spec_t *spec; unsigned int i; @@ -372,6 +373,49 @@ ogs_metrics_spec_t *ogs_metrics_spec_new( spec->prom = prom_gauge_new(spec->name, spec->description, spec->num_labels, (const char **)spec->labels); break; + case OGS_METRICS_METRIC_TYPE_HISTOGRAM: { + prom_histogram_buckets_t *buckets; + switch (histogram_params->type) { + case OGS_METRICS_HISTOGRAM_BUCKET_TYPE_EXPONENTIAL: + buckets = prom_histogram_buckets_exponential(histogram_params->exp.start, + histogram_params->exp.factor, histogram_params->count); + ogs_assert(buckets); + break; + case OGS_METRICS_HISTOGRAM_BUCKET_TYPE_LINEAR: + buckets = prom_histogram_buckets_linear(histogram_params->lin.start, + histogram_params->lin.width, histogram_params->count); + ogs_assert(buckets); + break; + case OGS_METRICS_HISTOGRAM_BUCKET_TYPE_VARIABLE: + { + double *upper_bounds; + + buckets = (prom_histogram_buckets_t *)prom_malloc(sizeof(prom_histogram_buckets_t)); + ogs_assert(buckets); + + ogs_assert(histogram_params->count <= OGS_METRICS_HIST_VAR_BUCKETS_MAX); + buckets->count = histogram_params->count; + + upper_bounds = (double *)prom_malloc( + sizeof(double) * histogram_params->count); + ogs_assert(upper_bounds); + for (i = 0; i < histogram_params->count; i++) { + upper_bounds[i] = histogram_params->var.buckets[i]; + if (i > 0) + ogs_assert(upper_bounds[i] > upper_bounds[i - 1]); + } + buckets->upper_bounds = upper_bounds; + break; + } + default: + ogs_assert_if_reached(); + break; + } + spec->prom = prom_histogram_new(spec->name, spec->description, + buckets, spec->num_labels, (const char **)spec->labels); + ogs_assert(spec->prom); + break; + } default: ogs_assert_if_reached(); break; @@ -477,6 +521,10 @@ void ogs_metrics_inst_add(ogs_metrics_inst_t *inst, int val) else prom_gauge_sub(inst->spec->prom, (double)-1.0*(double)val, (const char **)inst->label_values); break; + case OGS_METRICS_METRIC_TYPE_HISTOGRAM: + ogs_assert(val >= 0); + prom_histogram_observe(inst->spec->prom, (double)val, (const char **)inst->label_values); + break; default: ogs_assert_if_reached(); break; diff --git a/lib/metrics/void/context.c b/lib/metrics/void/context.c index 9fdcaab1f..38e8d1d7e 100644 --- a/lib/metrics/void/context.c +++ b/lib/metrics/void/context.c @@ -70,7 +70,8 @@ void ogs_metrics_spec_final(ogs_metrics_context_t *ctx) ogs_metrics_spec_t *ogs_metrics_spec_new( ogs_metrics_context_t *ctx, ogs_metrics_metric_type_t type, const char *name, const char *description, - int initial_val, unsigned int num_labels, const char ** labels) + int initial_val, unsigned int num_labels, const char ** labels, + ogs_metrics_histogram_params_t *histogram_params) { return (ogs_metrics_spec_t *)1; } diff --git a/src/amf/metrics.c b/src/amf/metrics.c index 7721caf76..29618fe6d 100644 --- a/src/amf/metrics.c +++ b/src/amf/metrics.c @@ -10,6 +10,7 @@ typedef struct amf_metrics_spec_def_s { int initial_val; unsigned int num_labels; const char **labels; + ogs_metrics_histogram_params_t histogram_params; } amf_metrics_spec_def_t; /* Helper generic functions: */ @@ -39,8 +40,10 @@ static int amf_metrics_init_spec(ogs_metrics_context_t *ctx, for (i = 0; i < len; i++) { dst[i] = ogs_metrics_spec_new(ctx, src[i].type, src[i].name, src[i].description, - src[i].initial_val, src[i].num_labels, src[i].labels); + src[i].initial_val, src[i].num_labels, src[i].labels, + &src[i].histogram_params); } + return OGS_OK; } @@ -135,6 +138,18 @@ amf_metrics_spec_def_t amf_metrics_spec_def_global[_AMF_METR_GLOB_MAX] = { .name = "fivegs_amffunction_mm_confupdatesucc", .description = "Number of UE Configuration Update complete messages received by the AMF", }, +/* Global Histograms: */ +[AMF_METR_GLOB_HIST_REG_TIME] = { + .type = OGS_METRICS_METRIC_TYPE_HISTOGRAM, + .name = "fivegs_amffunction_rm_regtime", + .description = "Time of registration procedure", + .histogram_params = { + .type = OGS_METRICS_HISTOGRAM_BUCKET_TYPE_EXPONENTIAL, + .count = 8, + .exp.start = 20, + .exp.factor = 2, + }, +}, }; int amf_metrics_init_inst_global(void) { diff --git a/src/amf/metrics.h b/src/amf/metrics.h index ef0535d47..d5f817b3c 100644 --- a/src/amf/metrics.h +++ b/src/amf/metrics.h @@ -25,6 +25,7 @@ typedef enum amf_metric_type_global_s { AMF_METR_GLOB_CTR_AMF_AUTH_REJECT, AMF_METR_GLOB_CTR_MM_CONF_UPDATE, AMF_METR_GLOB_CTR_MM_CONF_UPDATE_SUCC, + AMF_METR_GLOB_HIST_REG_TIME, _AMF_METR_GLOB_MAX, } amf_metric_type_global_t; extern ogs_metrics_inst_t *amf_metrics_inst_global[_AMF_METR_GLOB_MAX]; diff --git a/src/mme/metrics.c b/src/mme/metrics.c index feadf05b6..b7eb31175 100644 --- a/src/mme/metrics.c +++ b/src/mme/metrics.c @@ -39,7 +39,8 @@ static int mme_metrics_init_spec(ogs_metrics_context_t *ctx, for (i = 0; i < len; i++) { dst[i] = ogs_metrics_spec_new(ctx, src[i].type, src[i].name, src[i].description, - src[i].initial_val, src[i].num_labels, src[i].labels); + src[i].initial_val, src[i].num_labels, src[i].labels, + NULL); } return OGS_OK; } diff --git a/src/pcf/metrics.c b/src/pcf/metrics.c index a7d375751..1ff961b23 100644 --- a/src/pcf/metrics.c +++ b/src/pcf/metrics.c @@ -40,7 +40,8 @@ static int pcf_metrics_init_spec(ogs_metrics_context_t *ctx, for (i = 0; i < len; i++) { dst[i] = ogs_metrics_spec_new(ctx, src[i].type, src[i].name, src[i].description, - src[i].initial_val, src[i].num_labels, src[i].labels); + src[i].initial_val, src[i].num_labels, src[i].labels, + NULL); } return OGS_OK; } diff --git a/src/smf/metrics.c b/src/smf/metrics.c index 45a684037..8c37c9424 100644 --- a/src/smf/metrics.c +++ b/src/smf/metrics.c @@ -39,7 +39,8 @@ static int smf_metrics_init_spec(ogs_metrics_context_t *ctx, for (i = 0; i < len; i++) { dst[i] = ogs_metrics_spec_new(ctx, src[i].type, src[i].name, src[i].description, - src[i].initial_val, src[i].num_labels, src[i].labels); + src[i].initial_val, src[i].num_labels, src[i].labels, + NULL); } return OGS_OK; } diff --git a/src/upf/metrics.c b/src/upf/metrics.c index f47d7d754..0d1d277ab 100644 --- a/src/upf/metrics.c +++ b/src/upf/metrics.c @@ -40,7 +40,8 @@ static int upf_metrics_init_spec(ogs_metrics_context_t *ctx, for (i = 0; i < len; i++) { dst[i] = ogs_metrics_spec_new(ctx, src[i].type, src[i].name, src[i].description, - src[i].initial_val, src[i].num_labels, src[i].labels); + src[i].initial_val, src[i].num_labels, src[i].labels, + NULL); } return OGS_OK; }