mirror of https://github.com/sipwise/rtpengine.git
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.
268 lines
8.3 KiB
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_ */
|