Explorar el Código

Add new stats type: descriptor fetch stats

This is used for the bridge authority currently, to get a better
intuition on how many descriptors are actually fetched from it and how
many fetches happen in total.

Implements ticket 4200.
Sebastian Hahn hace 12 años
padre
commit
03c06b629f
Se han modificado 6 ficheros con 141 adiciones y 1 borrados
  1. 5 0
      changes/ticket4200
  2. 9 1
      src/or/config.c
  3. 1 0
      src/or/dirserv.c
  4. 5 0
      src/or/main.c
  5. 116 0
      src/or/rephist.c
  6. 5 0
      src/or/rephist.h

+ 5 - 0
changes/ticket4200

@@ -0,0 +1,5 @@
+  o Minor features:
+    - The bridge authority now writes statistics on how many bridge
+      descriptors it gave out in total, and how unique descriptors
+      it gave out. Implements ticket 4200.
+

+ 9 - 1
src/or/config.c

@@ -1532,7 +1532,8 @@ options_act(const or_options_t *old_options)
 
   if (options->CellStatistics || options->DirReqStatistics ||
       options->EntryStatistics || options->ExitPortStatistics ||
-      options->ConnDirectionStatistics) {
+      options->ConnDirectionStatistics ||
+      options->BridgeAuthoritativeDir) {
     time_t now = time(NULL);
     int print_notice = 0;
     if ((!old_options || !old_options->CellStatistics) &&
@@ -1577,6 +1578,10 @@ options_act(const or_options_t *old_options)
         options->ConnDirectionStatistics) {
       rep_hist_conn_stats_init(now);
     }
+    if (!old_options || !old_options->BridgeAuthoritativeDir) {
+      rep_hist_desc_stats_init(now);
+      print_notice = 1;
+    }
     if (print_notice)
       log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
                  "the *-stats files that will first be written to the "
@@ -1598,6 +1603,9 @@ options_act(const or_options_t *old_options)
   if (old_options && old_options->ConnDirectionStatistics &&
       !options->ConnDirectionStatistics)
     rep_hist_conn_stats_term();
+  if (old_options && old_options->BridgeAuthoritativeDir &&
+      !options->BridgeAuthoritativeDir)
+    rep_hist_desc_stats_term();
 
   /* Check if we need to parse and add the EntryNodes config option. */
   if (options->EntryNodes &&

+ 1 - 0
src/or/dirserv.c

@@ -3509,6 +3509,7 @@ 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);
     body = signed_descriptor_get_body(sd);
     if (conn->zlib_state) {
       /* XXXX022 This 'last' business should actually happen on the last

+ 5 - 0
src/or/main.c

@@ -1268,6 +1268,11 @@ run_scheduled_events(time_t now)
       if (next_write && next_write < next_time_to_write_stats_files)
         next_time_to_write_stats_files = next_write;
     }
+    if (options->BridgeAuthoritativeDir) {
+      time_t next_write = rep_hist_desc_stats_write(time_to_write_stats_files);
+      if (next_write && next_write < next_time_to_write_stats_files)
+        next_time_to_write_stats_files = next_write;
+    }
     time_to_write_stats_files = next_time_to_write_stats_files;
   }
 

+ 116 - 0
src/or/rephist.c

@@ -2596,6 +2596,120 @@ rep_hist_buffer_stats_write(time_t now)
   return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL;
 }
 
+/*** Descriptor serving statistics ***/
+
+/** Digestmap to track which descriptors were downloaded this stats
+ *  collection interval. It maps descriptor digest to pointers to 1,
+ *  effectively turning this into a list. */
+static digestmap_t *served_descs = NULL;
+
+/** Number of how many descriptors were downloaded in total during this
+ * interval. */
+static unsigned long total_descriptor_downloads;
+
+/** Start time of served descs stats or 0 if we're not collecting those. */
+static time_t start_of_served_descs_stats_interval;
+
+/** Initialize descriptor stats. */
+void
+rep_hist_desc_stats_init(time_t now)
+{
+  if (served_descs) {
+    log_warn(LD_BUG, "Called rep_hist_desc_stats_init() when desc stats were "
+             "already initialized. This is probably harmless.");
+    return; // Already initialized
+  }
+  served_descs = digestmap_new();
+  total_descriptor_downloads = 0;
+  start_of_served_descs_stats_interval = now;
+}
+
+/** Reset served descs stats to empty, starting a new interval <b>now</b>. */
+static void
+rep_hist_reset_desc_stats(time_t now)
+{
+  rep_hist_desc_stats_term();
+  rep_hist_desc_stats_init(now);
+}
+
+/** Stop collecting served descs stats, so that rep_hist_desc_stats_init() is
+ * safe to be called again. */
+void
+rep_hist_desc_stats_term(void)
+{
+  digestmap_free(served_descs, NULL);
+  served_descs = NULL;
+  start_of_served_descs_stats_interval = 0;
+  total_descriptor_downloads = 0;
+}
+
+/** Helper for rep_hist_desc_stats_write(). Return a newly allocated string
+ * containing the served desc statistics until now, or NULL if we're not
+ * collecting served desc stats. Caller must ensure that now is not before
+ * start_of_served_descs_stats_interval. */
+static char *
+rep_hist_format_desc_stats(time_t now)
+{
+  char t[ISO_TIME_LEN+1];
+  char *result;
+
+  if (!start_of_served_descs_stats_interval)
+    return NULL;
+
+  format_iso_time(t, now);
+
+  tor_asprintf(&result,
+               "served-descs-stats-end %s (%d s) total=%lu unique=%u\n",
+               t,
+               (unsigned) (now - start_of_served_descs_stats_interval),
+               total_descriptor_downloads,
+               digestmap_size(served_descs));
+
+  return result;
+}
+
+/** If WRITE_STATS_INTERVAL seconds have passed since the beginning of
+ * the current served desc stats interval, write the stats to
+ * $DATADIR/stats/served-desc-stats (possibly appending to an existing file)
+ * and reset the state for the next interval. Return when we would next want
+ * to write served desc stats or 0 if we won't want to write. */
+time_t
+rep_hist_desc_stats_write(time_t now)
+{
+  char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+  if (!start_of_served_descs_stats_interval)
+    return 0; /* We're not collecting stats. */
+  if (start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL > now)
+    return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL;
+
+  str = rep_hist_format_desc_stats(now);
+
+  statsdir = get_datadir_fname("stats");
+  if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+    log_warn(LD_HIST, "Unable to create stats/ directory!");
+      goto done;
+  }
+  filename = get_datadir_fname2("stats", "served-desc-stats");
+  if (append_bytes_to_file(filename, str, strlen(str), 0) < 0)
+    log_warn(LD_HIST, "Unable to write served descs statistics to disk!");
+
+  rep_hist_reset_desc_stats(now);
+
+ done:
+  tor_free(statsdir);
+  tor_free(filename);
+  tor_free(str);
+  return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL;
+}
+
+void
+rep_hist_note_desc_served(const char * desc)
+{
+  digestmap_set(served_descs, desc, (void *)1);
+  total_descriptor_downloads++;
+}
+
 /*** Connection statistics ***/
 
 /** Start of the current connection stats interval or 0 if we're not
@@ -2839,5 +2953,7 @@ rep_hist_free_all(void)
     smartlist_free(circuits_for_buffer_stats);
     circuits_for_buffer_stats = NULL;
   }
+  rep_hist_desc_stats_term();
+  total_descriptor_downloads = 0;
 }
 

+ 5 - 0
src/or/rephist.h

@@ -82,6 +82,11 @@ void rep_hist_add_buffer_stats(double mean_num_cells_in_queue,
 char *rep_hist_format_buffer_stats(time_t now);
 void rep_hist_reset_buffer_stats(time_t now);
 
+void rep_hist_desc_stats_init(time_t now);
+void rep_hist_note_desc_served(const char * desc);
+void rep_hist_desc_stats_term(void);
+time_t rep_hist_desc_stats_write(time_t now);
+
 void rep_hist_conn_stats_init(time_t now);
 void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
                                  size_t num_written, time_t when);