Commit ed174245 authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

implement more fine-tuning options for stats code

svn:r15345
parent 2e5e2f94
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -183,6 +183,9 @@ static config_var_t _option_vars[] = {
  OBSOLETE("DirPostPeriod"),
#ifdef ENABLE_GEOIP_STATS
  V(DirRecordUsageByCountry,     BOOL,     "0"),
  V(DirRecordUsageGranularity,   UINT,     "4"),
  V(DirRecordUsageRetainIPs,     INTERVAL, "14 days"),
  V(DirRecordUsageSaveInterval,  INTERVAL, "6 hours"),
#endif
  VAR("DirServer",               LINELIST, DirServers, NULL),
  V(DNSPort,                     UINT,     "0"),
+41 −11
Original line number Diff line number Diff line
@@ -408,6 +408,14 @@ _c_hist_compare(const void **_a, const void **_b)
/*DOCDOC*/
#define GEOIP_MIN_OBSERVATION_TIME (12*60*60)

static INLINE unsigned
round_to_next_multiple_of(unsigned number, unsigned divisor)
{
  number += divisor - 1;
  number -= number % divisor;
  return number;
}

/** Return a newly allocated comma-separated string containing entries for all
 * the countries from which we've seen enough clients connect. The entry
 * format is cc=num where num is the number of IPs we've seen connecting from
@@ -428,6 +436,11 @@ geoip_get_client_history(time_t now, geoip_client_action_t action)
    clientmap_entry_t **ent;
    unsigned *counts = tor_malloc_zero(sizeof(unsigned)*n_countries);
    unsigned total = 0;
    unsigned granularity = IP_GRANULARITY;
#ifdef ENABLE_GEOIP_STATS
    if (get_options()->DirRecordUsageByCountry)
      granularity = get_options()->DirRecordUsageGranularity;
#endif
    HT_FOREACH(ent, clientmap, &client_history) {
      int country;
      if (((*ent)->last_seen & ACTION_MASK) != action)
@@ -456,9 +469,7 @@ geoip_get_client_history(time_t now, geoip_client_action_t action)
#else
      if (c > 0) {
#endif
        /* Round up to the next multiple of IP_GRANULARITY */
        c += IP_GRANULARITY-1;
        c -= c % IP_GRANULARITY;
        c = round_to_next_multiple_of(c, granularity);
        countrycode = geoip_get_country_name(i);
        ent = tor_malloc(sizeof(c_hist_t));
        strlcpy(ent->country, countrycode, sizeof(ent->country));
@@ -497,8 +508,14 @@ geoip_get_client_history(time_t now, geoip_client_action_t action)
char *
geoip_get_request_history(time_t now, geoip_client_action_t action)
{
  smartlist_t *entries;
  smartlist_t *entries, *strings;
  char *result;
  unsigned granularity = IP_GRANULARITY;
#ifdef ENABLE_GEOIP_STATS
  if (get_options()->DirRecordUsageByCountry)
    granularity = get_options()->DirRecordUsageGranularity;
#endif

  if (client_history_starts >= (now - GEOIP_MIN_OBSERVATION_TIME))
    return NULL;
  if (action != GEOIP_CLIENT_NETWORKSTATUS &&
@@ -506,23 +523,36 @@ geoip_get_request_history(time_t now, geoip_client_action_t action)
    return NULL;
  if (!geoip_countries)
    return NULL;

  entries = smartlist_create();
  SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, {
      uint32_t *n = (action == GEOIP_CLIENT_NETWORKSTATUS)
        ? c->n_v3_ns_requests : c->n_v2_ns_requests;
      uint32_t tot = 0;
      int i;
      char buf[32];
      c_hist_t *ent;
      for (i=0; i < REQUEST_HIST_LEN; ++i)
        tot += n[i];
      if (!tot)
        continue;
      tor_snprintf(buf, sizeof(buf), "%s=%ld", c->countrycode, (long)tot);
      smartlist_add(entries, tor_strdup(buf));
      ent = tor_malloc_zero(sizeof(c_hist_t));
      strlcpy(ent->country, c->countrycode, sizeof(ent->country));
      ent->total = round_to_next_multiple_of(tot, granularity);
      smartlist_add(entries, ent);
  });
  smartlist_sort_strings(entries);
  result = smartlist_join_strings(entries, ",", 0, NULL);
  SMARTLIST_FOREACH(entries, char *, cp, tor_free(cp));
  smartlist_sort(entries, _c_hist_compare);

  strings = smartlist_create();
  SMARTLIST_FOREACH(entries, c_hist_t *, ent, {
      char buf[32];
      tor_snprintf(buf, sizeof(buf), "%s=%u", ent->country, ent->total);
      smartlist_add(strings, tor_strdup(buf));
    });
  result = smartlist_join_strings(strings, ",", 0, NULL);
  SMARTLIST_FOREACH(strings, char *, cp, tor_free(cp));
  SMARTLIST_FOREACH(entries, c_hist_t *, ent, tor_free(ent));
  smartlist_free(strings);
  smartlist_free(entries);
  return result;
}

+3 −0
Original line number Diff line number Diff line
@@ -2396,6 +2396,9 @@ typedef struct {
  int BridgeRecordUsageByCountry;
#ifdef ENABLE_GEOIP_STATS
  int DirRecordUsageByCountry;
  int DirRecordUsageGranularity;
  int DirRecordUsageRetainIPs;
  int DirRecordUsageSaveInterval;
#endif

  /** Optionally, a file with GeoIP data. */
+7 −2
Original line number Diff line number Diff line
@@ -1826,8 +1826,13 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
    static time_t last_purged_at = 0;
    char *geoip_summary;
    time_t now = time(NULL);
    if (now > last_purged_at+48*60*60) {
      geoip_remove_old_clients(now-48*60*60);
    int geoip_purge_interval = 48*60*60;
#ifdef ENABLE_GEOIP_STATS
    if (get_options()->DirRecordUsageByCountry)
      geoip_purge_interval = get_options()->DirRecordUsageRetainIPs;
#endif
    if (now > last_purged_at+geoip_purge_interval) {
      geoip_remove_old_clients(now-geoip_purge_interval);
      last_purged_at = now;
    }
    geoip_summary = geoip_get_client_history(time(NULL), GEOIP_CLIENT_CONNECT);