core: Extend rate_ctr by helper functions
For global value reporting, some additional helper functions are
needed. The statsd protocol expects differential counter values,
which are currently not provided by rate_ctr (except for s/m/h/d
intervals).
This commit adds several helper functions to rate_ctr:
- rate_ctr_difference returns the counter delta since the last
call to this function for a given counter
- rate_ctr_for_each_counter
iterates through each counter of a group
- rate_ctr_for_each_group
iterates through all globally registered
counter groups
Note that the rate_ctr_difference function can only be used by a
single backend, since it modifies the 'previous' field in the
rate_ctr obj.
Sponsored-by: On-Waves ehf
diff --git a/include/osmocom/core/rate_ctr.h b/include/osmocom/core/rate_ctr.h
index 821c7cf..f3c03de 100644
--- a/include/osmocom/core/rate_ctr.h
+++ b/include/osmocom/core/rate_ctr.h
@@ -30,6 +30,7 @@
/*! \brief data we keep for each actual value */
struct rate_ctr {
uint64_t current; /*!< \brief current value */
+ uint64_t previous; /*!< \brief previous value, used for delta */
/*! \brief per-interval data */
struct rate_ctr_per_intv intv[RATE_CTR_INTV_NUM];
};
@@ -78,9 +79,27 @@
rate_ctr_add(ctr, 1);
}
+/*! \brief Return the counter difference since the last call to this function */
+int64_t rate_ctr_difference(struct rate_ctr *ctr);
+
int rate_ctr_init(void *tall_ctx);
struct rate_ctr_group *rate_ctr_get_group_by_name_idx(const char *name, const unsigned int idx);
const struct rate_ctr *rate_ctr_get_by_name(const struct rate_ctr_group *ctrg, const char *name);
+typedef int (*rate_ctr_handler_t)(
+ struct rate_ctr_group *, struct rate_ctr *,
+ const struct rate_ctr_desc *, void *);
+typedef int (*rate_ctr_group_handler_t)(struct rate_ctr_group *, void *);
+
+
+/*! \brief Iterate over all counters
+ * \param[in] handle_item Call-back function, aborts if rc < 0
+ * \param[in] data Private data handed through to \a handle_counter
+ */
+int rate_ctr_for_each_counter(struct rate_ctr_group *ctrg,
+ rate_ctr_handler_t handle_counter, void *data);
+
+int rate_ctr_for_each_group(rate_ctr_group_handler_t handle_group, void *data);
+
/*! @} */
diff --git a/src/rate_ctr.c b/src/rate_ctr.c
index 8a232e8..50b3fe7 100644
--- a/src/rate_ctr.c
+++ b/src/rate_ctr.c
@@ -83,6 +83,15 @@
ctr->current += inc;
}
+/*! \brief Return the counter difference since the last call to this function */
+int64_t rate_ctr_difference(struct rate_ctr *ctr)
+{
+ int64_t result = ctr->current - ctr->previous;
+ ctr->previous = ctr->current;
+
+ return result;
+}
+
static void interval_expired(struct rate_ctr *ctr, enum rate_ctr_intv intv)
{
/* calculate rate over last interval */
@@ -177,4 +186,36 @@
return NULL;
}
+int rate_ctr_for_each_counter(struct rate_ctr_group *ctrg,
+ rate_ctr_handler_t handle_counter, void *data)
+{
+ int rc = 0;
+ int i;
+
+ for (i = 0; i < ctrg->desc->num_ctr; i++) {
+ struct rate_ctr *ctr = &ctrg->ctr[i];
+ rc = handle_counter(ctrg,
+ ctr, &ctrg->desc->ctr_desc[i], data);
+ if (rc < 0)
+ return rc;
+ }
+
+ return rc;
+}
+
+int rate_ctr_for_each_group(rate_ctr_group_handler_t handle_group, void *data)
+{
+ struct rate_ctr_group *statg;
+ int rc = 0;
+
+ llist_for_each_entry(statg, &rate_ctr_groups, list) {
+ rc = handle_group(statg, data);
+ if (rc < 0)
+ return rc;
+ }
+
+ return rc;
+}
+
+
/*! @} */