You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rtpengine/include/statistics.h

268 lines
8.3 KiB

#ifndef STATISTICS_H_
#define STATISTICS_H_
#include "helpers.h"
#include "bencode.h"
#include "control_ng.h"
#include "graphite.h"
// "gauge" style stats
struct global_stats_gauge {
#define F(x) atomic64 x;
#include "gauge_stats_fields.inc"
#undef F
};
// high/low water marks
struct global_gauge_min_max {
struct global_stats_gauge min;
struct global_stats_gauge max;
};
// "sampled" style stats
struct global_stats_sampled_fields {
#define F(x) atomic64 x;
#define FA(x, n) atomic64 x[n];
#include "sampled_stats_fields.inc"
#undef F
#undef FA
};
struct global_stats_sampled {
struct global_stats_sampled_fields sums;
struct global_stats_sampled_fields sums_squared;
struct global_stats_sampled_fields counts;
};
struct global_sampled_min_max {
struct global_stats_sampled_fields min;
struct global_stats_sampled_fields max;
};
struct global_sampled_avg {
struct global_stats_sampled_fields avg;
struct global_stats_sampled_fields stddev;
};
// "counter" style stats that are incremental and are kept cumulative or per-interval
struct global_stats_counter {
#define F(x) atomic64 x;
#define FA(x, n) atomic64 x[n];
#include "counter_stats_fields.inc"
#undef F
#undef FA
};
struct global_rate_min_max {
struct global_stats_counter min;
struct global_stats_counter max;
};
struct global_rate_min_max_avg {
struct global_stats_counter min;
struct global_stats_counter max;
struct global_stats_counter avg;
};
struct codec_stats {
char *chain;
char *chain_brief;
int num_transcoders;
// 3 entries: [0] and [1] for per-second stats, [2] for total count
// last_tv_sec keeps track of rollovers
int last_tv_sec[2];
atomic64 packets_input[3];
atomic64 bytes_input[3];
atomic64 pcm_samples[3];
};
struct stats_metric {
char *label;
char *descr;
char *value_short;
char *value_long;
char *value_raw;
int64_t int_value;
double double_value;
int is_bracket;
int is_close_bracket;
int is_brace;
int is_follow_up;
int is_int;
int is_double;
const char *prom_name;
const char *prom_type;
char *prom_label;
};
TYPED_GQUEUE(stats_metric, stats_metric)
struct call_stats {
int64_t last_packet_us;
struct stream_stats totals[4]; /* rtp in, rtcp in, rtp out, rtcp out */
};
extern int64_t rtpe_started;
extern mutex_t rtpe_codec_stats_lock;
extern codec_stats_ht rtpe_codec_stats;
extern struct global_stats_gauge rtpe_stats_gauge; // master values
extern struct global_gauge_min_max rtpe_gauge_min_max; // master lifetime min/max
#define RTPE_GAUGE_SET_MIN_MAX(field, min_max_struct, val) \
do { \
atomic64_min(&min_max_struct.min.field, val); \
atomic64_max(&min_max_struct.max.field, val); \
} while (0)
#define RTPE_GAUGE_SET(field, num) \
do { \
atomic64_set_na(&rtpe_stats_gauge.field, num); \
RTPE_GAUGE_SET_MIN_MAX(field, rtpe_gauge_min_max, num); \
if (graphite_is_enabled()) \
RTPE_GAUGE_SET_MIN_MAX(field, rtpe_gauge_graphite_min_max, num); \
} while (0)
#define RTPE_GAUGE_ADD(field, num) \
do { \
uint64_t __old = atomic64_add_na(&rtpe_stats_gauge.field, num); \
RTPE_GAUGE_SET_MIN_MAX(field, rtpe_gauge_min_max, __old + num); \
if (graphite_is_enabled()) \
RTPE_GAUGE_SET_MIN_MAX(field, rtpe_gauge_graphite_min_max, __old + num); \
} while (0)
#define RTPE_GAUGE_INC(field) RTPE_GAUGE_ADD(field, 1)
#define RTPE_GAUGE_DEC(field) RTPE_GAUGE_ADD(field, -1)
extern struct global_stats_sampled rtpe_stats_sampled; // master cumulative values
extern struct global_sampled_min_max rtpe_sampled_min_max; // master lifetime min/max
#define RTPE_STATS_SAMPLE(field, num) \
do { \
atomic64_add_na(&rtpe_stats_sampled.sums.field, num); \
atomic64_add_na(&rtpe_stats_sampled.sums_squared.field, num * num); \
atomic64_inc_na(&rtpe_stats_sampled.counts.field); \
RTPE_GAUGE_SET_MIN_MAX(field, rtpe_sampled_min_max, num); \
RTPE_GAUGE_SET_MIN_MAX(field, rtpe_sampled_graphite_min_max, num); \
} while (0)
// TODO: ^ skip doing this for graphite if it's not actually enabled
#define RTPE_SAMPLE_SFD(field, num, sfd) \
do { \
RTPE_STATS_SAMPLE(field, num); \
if (sfd) { \
struct local_intf *__intf = sfd->local_intf; \
atomic64_add_na(&__intf->stats->sampled.sums.field, num); \
atomic64_add_na(&__intf->stats->sampled.sums_squared.field, num * num); \
atomic64_inc_na(&__intf->stats->sampled.counts.field); \
} \
} while (0)
extern struct global_stats_counter *rtpe_stats; // total, cumulative, master
extern struct global_stats_counter rtpe_stats_rate; // per-second, calculated once per timer run
extern struct global_stats_counter rtpe_stats_intv; // per-second, calculated once per timer run
#define RTPE_STATS_ADD(field, num) atomic64_add_na(&rtpe_stats->field, num)
#define RTPE_STATS_INC(field) RTPE_STATS_ADD(field, 1)
void statistics_update_oneway(call_t *);
void statistics_update_ip46_inc_dec(call_t *, int op);
void statistics_update_foreignown_dec(call_t *);
void statistics_update_foreignown_inc(call_t * c);
stats_metric_q *statistics_gather_metrics(struct interface_sampled_rate_stats *);
void statistics_free_metrics(stats_metric_q *);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(stats_metric_q, statistics_free_metrics)
const char *statistics_ng(ng_command_ctx_t *);
enum thread_looper_action call_rate_stats_updater(void);
/**
* Calculation of the call rate counters.
* If used with the `stats_rate_min_max()` must only be called in advance, so before that.
*/
INLINE void stats_counters_calc_rate(const struct global_stats_counter *stats, int64_t run_diff_us,
struct global_stats_counter *intv, struct global_stats_counter *rate)
{
#define F(x) atomic64_calc_rate(&stats->x, run_diff_us, &intv->x, &rate->x);
#define FA(x, n) for (int i = 0; i < n; i++) { F(x[i]) }
#include "counter_stats_fields.inc"
#undef F
#undef FA
}
INLINE void stats_counters_calc_diff(const struct global_stats_counter *stats,
struct global_stats_counter *intv, struct global_stats_counter *diff)
{
#define F(x) atomic64_calc_diff(&stats->x, &intv->x, &diff->x);
#define FA(x, n) for (int i = 0; i < n; i++) { F(x[i]) }
#include "counter_stats_fields.inc"
#undef F
#undef FA
}
/**
* Update the running min/max counter `mm` with the newly calculated per-sec rate values `inp`.
* If used with the `stats_counters_calc_rate()`, it must be called only after that.
*/
INLINE void stats_rate_min_max(struct global_rate_min_max *mm, struct global_stats_counter *inp) {
#define F(x) \
atomic64_mina(&mm->min.x, &inp->x); \
atomic64_maxa(&mm->max.x, &inp->x);
#define FA(x, n) for (int i = 0; i < n; i++) { F(x[i]) }
#include "counter_stats_fields.inc"
#undef F
#undef FA
}
// sample running min/max from `mm` into `loc` and reset `mm` to zero.
// calculate average values in `loc` from `counter_diff` and `time_diff_us`
INLINE void stats_rate_min_max_avg_sample(struct global_rate_min_max *mm, struct global_rate_min_max_avg *loc,
int64_t run_diff_us, const struct global_stats_counter *counter_diff) {
#define F(x) STAT_MIN_MAX_AVG(x, mm, loc, run_diff_us, counter_diff)
#define FA(x, n) for (int i = 0; i < n; i++) { F(x[i]) }
#include "counter_stats_fields.inc"
#undef F
#undef FA
}
INLINE void stats_sampled_calc_diff(const struct global_stats_sampled *stats,
struct global_stats_sampled *intv, struct global_stats_sampled *diff)
{
#define F(x) STAT_SAMPLED_CALC_DIFF(x, stats, intv, diff)
#define FA(x, n) for (int i = 0; i < n; i++) { F(x[i]) }
#include "sampled_stats_fields.inc"
#undef F
#undef FA
}
// sample running min/max from `mm` into `loc` and reset `mm` to zero.
INLINE void stats_sampled_min_max_sample(struct global_sampled_min_max *mm,
struct global_sampled_min_max *loc) {
#define F(x) STAT_MIN_MAX_RESET_ZERO(x, mm, loc)
#define FA(x, n) for (int i = 0; i < n; i++) { F(x[i]) }
#include "sampled_stats_fields.inc"
#undef F
#undef FA
}
INLINE void stats_sampled_avg(struct global_sampled_avg *loc,
const struct global_stats_sampled *diff) {
#define F(x) STAT_SAMPLED_AVG_STDDEV(x, loc, diff)
#define FA(x, n) for (int i = 0; i < n; i++) { F(x[i]) }
#include "sampled_stats_fields.inc"
#undef F
#undef FA
}
// sample running min/max from `in_reset` into `out` and reset `in_reset` to the current value.
INLINE void stats_gauge_min_max_sample(struct global_gauge_min_max *out,
struct global_gauge_min_max *in_reset, const struct global_stats_gauge *cur)
{
#define F(x) STAT_MIN_MAX(x, out, in_reset, cur)
#include "gauge_stats_fields.inc"
#undef F
}
void statistics_init(void);
void statistics_free(void);
#endif /* STATISTICS_H_ */