|
|
|
|
@ -521,6 +521,7 @@ GQueue *statistics_gather_metrics(void) {
|
|
|
|
|
total.play_media += cur->play_media;
|
|
|
|
|
total.stop_media += cur->stop_media;
|
|
|
|
|
total.play_dtmf += cur->play_dtmf;
|
|
|
|
|
total.statistics += cur->statistics;
|
|
|
|
|
total.errors += cur->errors;
|
|
|
|
|
HEADER("{", NULL);
|
|
|
|
|
METRICsva("proxy", "\"%s\"", sockaddr_print_buf(&cur->proxy));
|
|
|
|
|
@ -541,6 +542,7 @@ GQueue *statistics_gather_metrics(void) {
|
|
|
|
|
METRICs("playmedia", "%u", cur->play_media);
|
|
|
|
|
METRICs("stopmedia", "%u", cur->stop_media);
|
|
|
|
|
METRICs("playdtmf", "%u", cur->play_dtmf);
|
|
|
|
|
METRICs("statistics", "%u", cur->statistics);
|
|
|
|
|
METRICs("errorcount", "%u", cur->errors);
|
|
|
|
|
HEADER("}", NULL);
|
|
|
|
|
|
|
|
|
|
@ -567,6 +569,7 @@ GQueue *statistics_gather_metrics(void) {
|
|
|
|
|
METRICs("totalplaymedia", "%u", total.play_media);
|
|
|
|
|
METRICs("totalstopmedia", "%u", total.stop_media);
|
|
|
|
|
METRICs("totalplaydtmf", "%u", total.play_dtmf);
|
|
|
|
|
METRICs("totalstatistics", "%u", total.statistics);
|
|
|
|
|
METRICs("totalerrorcount", "%u", total.errors);
|
|
|
|
|
|
|
|
|
|
HEADER("}", "");
|
|
|
|
|
@ -613,3 +616,74 @@ void statistics_init() {
|
|
|
|
|
mutex_init(&rtpe_codec_stats_lock);
|
|
|
|
|
rtpe_codec_stats = g_hash_table_new(g_str_hash, g_str_equal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *statistics_ng(bencode_item_t *input, bencode_item_t *output) {
|
|
|
|
|
AUTO_CLEANUP_INIT(GQueue *metrics, statistics_free_metrics, statistics_gather_metrics());
|
|
|
|
|
AUTO_CLEANUP_INIT(GQueue bstack, g_queue_clear, G_QUEUE_INIT);
|
|
|
|
|
|
|
|
|
|
bencode_item_t *dict = output;
|
|
|
|
|
const char *sub_label = "statistics"; // top level
|
|
|
|
|
bencode_buffer_t *buf = output->buffer;
|
|
|
|
|
|
|
|
|
|
for (GList *l = metrics->head; l; l = l->next) {
|
|
|
|
|
struct stats_metric *m = l->data;
|
|
|
|
|
if (!m->label)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// key:value entry?
|
|
|
|
|
if (m->value_short) {
|
|
|
|
|
if (m->is_int)
|
|
|
|
|
bencode_dictionary_add_integer(dict, bencode_strdup(buf, m->label),
|
|
|
|
|
m->int_value);
|
|
|
|
|
else {
|
|
|
|
|
size_t len = strlen(m->value_short);
|
|
|
|
|
if (len >= 2 && m->value_short[0] == '"' && m->value_short[len-1] == '"')
|
|
|
|
|
bencode_dictionary_add(dict, bencode_strdup(buf, m->label),
|
|
|
|
|
bencode_string_len_dup(buf, m->value_short+1, len-2));
|
|
|
|
|
else
|
|
|
|
|
bencode_dictionary_add_string_dup(dict, bencode_strdup(buf, m->label),
|
|
|
|
|
m->value_short);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// list or dict end?
|
|
|
|
|
if (m->is_close_bracket) {
|
|
|
|
|
dict = g_queue_pop_tail(&bstack);
|
|
|
|
|
assert(dict != NULL);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// label without value precedes an immediate sub-entry, so save the label
|
|
|
|
|
if (!m->is_bracket) {
|
|
|
|
|
assert(sub_label == NULL);
|
|
|
|
|
sub_label = m->label;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// open bracket of some sort - new sub-entry follows
|
|
|
|
|
bencode_item_t *sub = NULL;
|
|
|
|
|
if (m->is_brace)
|
|
|
|
|
sub = bencode_dictionary(buf);
|
|
|
|
|
else
|
|
|
|
|
sub = bencode_list(buf);
|
|
|
|
|
|
|
|
|
|
assert(sub != NULL);
|
|
|
|
|
|
|
|
|
|
// is this a dictionary?
|
|
|
|
|
if (dict->type == BENCODE_DICTIONARY) {
|
|
|
|
|
assert(sub_label != NULL);
|
|
|
|
|
bencode_dictionary_add(dict, bencode_strdup(buf, sub_label), sub);
|
|
|
|
|
}
|
|
|
|
|
else if (dict->type == BENCODE_LIST)
|
|
|
|
|
bencode_list_add(dict, sub);
|
|
|
|
|
else
|
|
|
|
|
abort();
|
|
|
|
|
|
|
|
|
|
sub_label = NULL;
|
|
|
|
|
g_queue_push_tail(&bstack, dict);
|
|
|
|
|
dict = sub;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|