diff --git a/changes/ticket4294 b/changes/ticket4294 new file mode 100644 index 0000000000..5041495542 --- /dev/null +++ b/changes/ticket4294 @@ -0,0 +1,8 @@ +(NOTE: THIS SHOULD REPLACE THE TICKET 4200 ENTRY IN THE CHANGELOG) + o Minor features: + - The Bridge Authority now writes statistics on how many bridge + descriptors it gave out in total, and how many unique descriptors it + gave out. It also lists how often the most and least commonly fetched + descriptors were given out, as well as the median and 25/75 percentile. + Implements tickets 4200 and 4294. + diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 4b9587b0fc..5cb4aba5aa 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -3488,6 +3488,8 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_DIGEST); time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH; + const or_options_t *options = get_options(); + while (smartlist_len(conn->fingerprint_stack) && connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) { const char *body; @@ -3509,7 +3511,16 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) * unknown bridge descriptor has shown up between then and now. */ continue; } - rep_hist_note_desc_served(sd->identity_digest); + + /** If we are the bridge authority and the descriptor is a bridge + * descriptor, remember that we served this descriptor for desc stats. */ + if (options->BridgeAuthoritativeDir && by_fp) { + const routerinfo_t *router = + router_get_by_id_digest(sd->identity_digest); + tor_assert(router); + if (router->purpose == ROUTER_PURPOSE_BRIDGE) + rep_hist_note_desc_served(sd->identity_digest); + } body = signed_descriptor_get_body(sd); if (conn->zlib_state) { /* XXXX022 This 'last' business should actually happen on the last diff --git a/src/or/rephist.c b/src/or/rephist.c index f8ebe644fc..359e4886a3 100644 --- a/src/or/rephist.c +++ b/src/or/rephist.c @@ -2643,7 +2643,7 @@ rep_hist_reset_desc_stats(time_t now) void rep_hist_desc_stats_term(void) { - digestmap_free(served_descs, NULL); + digestmap_free(served_descs, _tor_free); served_descs = NULL; start_of_served_descs_stats_interval = 0; total_descriptor_downloads = 0; @@ -2659,18 +2659,43 @@ rep_hist_format_desc_stats(time_t now) char t[ISO_TIME_LEN+1]; char *result; + digestmap_iter_t *iter; + const char *key; + void *val; + unsigned size; + int *vals; + int n = 0, *count; + if (!start_of_served_descs_stats_interval) return NULL; + size = digestmap_size(served_descs); + vals = tor_malloc(size * sizeof(int)); + + for (iter = digestmap_iter_init(served_descs); !digestmap_iter_done(iter); + iter = digestmap_iter_next(served_descs, iter) ) { + digestmap_iter_get(iter, &key, &val); + count = val; + vals[n++] = *count; + (void)key; + } + format_iso_time(t, now); tor_asprintf(&result, - "served-descs-stats-end %s (%d s) total=%lu unique=%u\n", + "served-descs-stats-end %s (%d s) total=%lu unique=%u " + "max=%d q3=%d md=%d q1=%d min=%d\n", t, (unsigned) (now - start_of_served_descs_stats_interval), total_descriptor_downloads, - digestmap_size(served_descs)); + size, + find_nth_int(vals, size, size-1), + find_nth_int(vals, size, (3*size-1)/4), + find_nth_int(vals, size, (size-1)/2), + find_nth_int(vals, size, (size-1)/4), + find_nth_int(vals, size, 0)); + tor_free(vals); return result; } @@ -2712,9 +2737,17 @@ rep_hist_desc_stats_write(time_t now) void rep_hist_note_desc_served(const char * desc) { + int *val; if (!served_descs) return; // We're not collecting stats - digestmap_set(served_descs, desc, (void *)1); + val = digestmap_get(served_descs, desc); + if (!val) { + val = tor_malloc(sizeof(int)); + *val = 1; + digestmap_set(served_descs, desc, val); + } else { + (*val)++; + } total_descriptor_downloads++; }