summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarsten Loesing <karsten.loesing@gmx.net>2009-08-19 15:41:12 +0200
committerKarsten Loesing <karsten.loesing@gmx.net>2009-08-19 15:41:12 +0200
commit4e29f3342754fa8802c364b58f7b2f98e983a291 (patch)
treef570d879362bf688ab1da6290689d1d099656df1
parent10fbc998e146b271508066e7680cb0cd00a70c63 (diff)
downloadtor-4e29f3342754fa8802c364b58f7b2f98e983a291.tar.gz
tor-4e29f3342754fa8802c364b58f7b2f98e983a291.zip
Write all statistics to disk exactly every 24 hours.
-rw-r--r--doc/tor.1.in12
-rw-r--r--src/or/circuitlist.c2
-rw-r--r--src/or/config.c40
-rw-r--r--src/or/connection.c4
-rw-r--r--src/or/connection_edge.c2
-rw-r--r--src/or/geoip.c106
-rw-r--r--src/or/main.c44
-rw-r--r--src/or/or.h22
-rw-r--r--src/or/rephist.c225
9 files changed, 237 insertions, 220 deletions
diff --git a/doc/tor.1.in b/doc/tor.1.in
index 54e35aa6c6..7606ffb69a 100644
--- a/doc/tor.1.in
+++ b/doc/tor.1.in
@@ -1060,24 +1060,26 @@ A filename containing GeoIP data, for use with BridgeRecordUsageByCountry.
.TP
\fBCellStatistics \fR\fB0\fR|\fB1\fR\fP
When this option is enabled, Tor writes statistics on the mean time that
-cells spend in circuit queues to disk every 24 hours. (Default: 0)
+cells spend in circuit queues to disk every 24 hours. Cannot be changed
+while Tor is running. (Default: 0)
.LP
.TP
\fBDirReqStatistics \fR\fB0\fR|\fB1\fR\fP
When this option is enabled, Tor writes statistics on the number and
-response time of network status requests to disk every 24 hours.
-(Default: 0)
+response time of network status requests to disk every 24 hours. Cannot be
+changed while Tor is running. (Default: 0)
.LP
.TP
\fBEntryStatistics \fR\fB0\fR|\fB1\fR\fP
When this option is enabled, Tor writes statistics on the number of
-directly connecting clients to disk every 24 hours. (Default: 0)
+directly connecting clients to disk every 24 hours. Cannot be changed
+while Tor is running. (Default: 0)
.LP
.TP
\fBExitPortStatistics \fR\fB0\fR|\fB1\fR\fP
When this option is enabled, Tor writes statistics on the number of
relayed bytes and opened stream per exit port to disk every 24 hours.
-(Default: 0)
+Cannot be changed while Tor is running. (Default: 0)
.LP
.TP
\fBExtraInfoStatistics \fR\fB0\fR|\fB1\fR\fP
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 04b1d8edb3..065559620c 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -449,7 +449,7 @@ circuit_free(circuit_t *circ)
or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
/* Remember cell statistics for this circuit before deallocating. */
if (get_options()->CellStatistics)
- add_circ_to_buffer_stats(circ, time(NULL));
+ rep_hist_buffer_stats_add_circ(circ, time(NULL));
mem = ocirc;
memlen = sizeof(or_circuit_t);
tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
diff --git a/src/or/config.c b/src/or/config.c
index 7b3f0ad07f..acc544b8b8 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -1407,29 +1407,13 @@ options_act(or_options_t *old_options)
tor_free(actual_fname);
}
- if (options->DirReqStatistics) {
+ if (options->DirReqStatistics && !geoip_is_loaded()) {
/* Check if GeoIP database could be loaded. */
- if (!geoip_is_loaded()) {
- log_warn(LD_CONFIG, "Configured to measure directory request "
- "statistics, but no GeoIP database found!");
- return -1;
- }
- log_notice(LD_CONFIG, "Configured to count directory requests by "
- "country and write aggregate statistics to disk. Check the "
- "dirreq-stats file in your data directory that will first "
- "be written in 24 hours from now.");
+ log_warn(LD_CONFIG, "Configured to measure directory request "
+ "statistics, but no GeoIP database found!");
+ return -1;
}
- if (options->ExitPortStatistics)
- log_notice(LD_CONFIG, "Configured to measure exit port statistics. "
- "Look for the exit-stats file that will first be written to "
- "the data directory in 24 hours from now.");
-
- if (options->CellStatistics)
- log_notice(LD_CONFIG, "Configured to measure cell statistics. Look "
- "for the buffer-stats file that will first be written to "
- "the data directory in 24 hours from now.");
-
if (options->EntryStatistics) {
if (should_record_bridge_info(options)) {
/* Don't allow measuring statistics on entry guards when configured
@@ -1442,11 +1426,7 @@ options_act(or_options_t *old_options)
log_warn(LD_CONFIG, "Configured to measure entry node statistics, "
"but no GeoIP database found!");
return -1;
- } else
- log_notice(LD_CONFIG, "Configured to measure entry node "
- "statistics. Look for the entry-stats file that will "
- "first be written to the data directory in 24 hours "
- "from now.");
+ }
}
/* Check if we need to parse and add the EntryNodes config option. */
@@ -3784,6 +3764,16 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val,
return -1;
}
+ if (old->CellStatistics != new_val->CellStatistics ||
+ old->DirReqStatistics != new_val->DirReqStatistics ||
+ old->EntryStatistics != new_val->EntryStatistics ||
+ old->ExitPortStatistics != new_val->ExitPortStatistics) {
+ *msg = tor_strdup("While Tor is running, changing either "
+ "CellStatistics, DirReqStatistics, EntryStatistics, "
+ "or ExitPortStatistics is not allowed.");
+ return -1;
+ }
+
return 0;
}
diff --git a/src/or/connection.c b/src/or/connection.c
index 48f8278573..c961f16c6c 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1704,12 +1704,12 @@ connection_buckets_decrement(connection_t *conn, time_t now,
if (num_read > 0) {
if (conn->type == CONN_TYPE_EXIT)
- rep_hist_note_exit_bytes_read(conn->port, num_read, now);
+ rep_hist_note_exit_bytes_read(conn->port, num_read);
rep_hist_note_bytes_read(num_read, now);
}
if (num_written > 0) {
if (conn->type == CONN_TYPE_EXIT)
- rep_hist_note_exit_bytes_written(conn->port, num_written, now);
+ rep_hist_note_exit_bytes_written(conn->port, num_written);
rep_hist_note_bytes_written(num_written, now);
}
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 1df576d636..f25202725e 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -333,7 +333,7 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
escaped_safe_str(conn->address),conn->port,
safe_str(fmt_addr(&conn->addr)));
- rep_hist_note_exit_stream_opened(conn->port, approx_time());
+ rep_hist_note_exit_stream_opened(conn->port);
conn->state = EXIT_CONN_STATE_OPEN;
connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
diff --git a/src/or/geoip.c b/src/or/geoip.c
index 824428b7d9..9f37c021c1 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -12,8 +12,6 @@
#include "ht.h"
static void clear_geoip_db(void);
-static void dump_geoip_stats(void);
-static void dump_entry_stats(void);
/** An entry from the GeoIP file: maps an IP range to a country. */
typedef struct geoip_entry_t {
@@ -390,37 +388,6 @@ geoip_note_client_seen(geoip_client_action_t action,
return;
}
- /* Rotate the current request period. */
- while (current_request_period_starts + REQUEST_HIST_PERIOD < now) {
- if (!geoip_countries)
- geoip_countries = smartlist_create();
- if (!current_request_period_starts) {
- current_request_period_starts = now;
- break;
- }
- /* Also discard all items in the client history that are too old.
- * (This only works here because bridge and directory stats are
- * independent. Otherwise, we'd only want to discard those items
- * with action GEOIP_CLIENT_NETWORKSTATUS{_V2}.) */
- geoip_remove_old_clients(current_request_period_starts);
- /* Before rotating, write the current stats to disk. */
- dump_geoip_stats();
- if (get_options()->EntryStatistics)
- dump_entry_stats();
- /* Now rotate request period */
- SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, {
- memmove(&c->n_v2_ns_requests[0], &c->n_v2_ns_requests[1],
- sizeof(uint32_t)*(REQUEST_HIST_LEN-1));
- memmove(&c->n_v3_ns_requests[0], &c->n_v3_ns_requests[1],
- sizeof(uint32_t)*(REQUEST_HIST_LEN-1));
- c->n_v2_ns_requests[REQUEST_HIST_LEN-1] = 0;
- c->n_v3_ns_requests[REQUEST_HIST_LEN-1] = 0;
- });
- current_request_period_starts += REQUEST_HIST_PERIOD;
- if (n_old_request_periods < REQUEST_HIST_LEN-1)
- ++n_old_request_periods;
- }
-
lookup.ipaddr = addr;
lookup.action = (int)action;
ent = HT_FIND(clientmap, &client_history, &lookup);
@@ -940,12 +907,20 @@ geoip_get_request_history(time_t now, geoip_client_action_t action)
return result;
}
+/** Start time of directory request stats. */
+static time_t start_of_dirreq_stats_interval;
+
+/** Initialize directory request stats. */
+void
+geoip_dirreq_stats_init(time_t now)
+{
+ start_of_dirreq_stats_interval = now;
+}
+
/** Store all our geoip statistics into $DATADIR/dirreq-stats. */
-static void
-dump_geoip_stats(void)
+void
+geoip_dirreq_stats_write(time_t now)
{
- time_t now = time(NULL);
- time_t request_start;
char *filename = get_datadir_fname("dirreq-stats");
char *data_v2 = NULL, *data_v3 = NULL;
char written[ISO_TIME_LEN+1];
@@ -957,11 +932,14 @@ dump_geoip_stats(void)
if (!get_options()->DirReqStatistics)
goto done;
+ /* Discard all items in the client history that are too old. */
+ geoip_remove_old_clients(start_of_dirreq_stats_interval);
+
data_v2 = geoip_get_client_history_dirreq(now,
GEOIP_CLIENT_NETWORKSTATUS_V2);
data_v3 = geoip_get_client_history_dirreq(now,
GEOIP_CLIENT_NETWORKSTATUS);
- format_iso_time(written, geoip_get_history_start() + REQUEST_HIST_PERIOD);
+ format_iso_time(written, now);
out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND,
0600, &open_file);
if (!out)
@@ -973,8 +951,6 @@ dump_geoip_stats(void)
tor_free(data_v2);
tor_free(data_v3);
- request_start = current_request_period_starts -
- (n_old_request_periods * REQUEST_HIST_PERIOD);
data_v2 = geoip_get_request_history(now, GEOIP_CLIENT_NETWORKSTATUS_V2);
data_v3 = geoip_get_request_history(now, GEOIP_CLIENT_NETWORKSTATUS);
if (fprintf(out, "dirreq-v3-reqs %s\ndirreq-v2-reqs %s\n",
@@ -1033,6 +1009,22 @@ dump_geoip_stats(void)
finish_writing_to_file(open_file);
open_file = NULL;
+
+ /* Rotate request period */
+ SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, {
+ memmove(&c->n_v2_ns_requests[0], &c->n_v2_ns_requests[1],
+ sizeof(uint32_t)*(REQUEST_HIST_LEN-1));
+ memmove(&c->n_v3_ns_requests[0], &c->n_v3_ns_requests[1],
+ sizeof(uint32_t)*(REQUEST_HIST_LEN-1));
+ c->n_v2_ns_requests[REQUEST_HIST_LEN-1] = 0;
+ c->n_v3_ns_requests[REQUEST_HIST_LEN-1] = 0;
+ });
+ current_request_period_starts += REQUEST_HIST_PERIOD;
+ if (n_old_request_periods < REQUEST_HIST_LEN-1)
+ ++n_old_request_periods;
+
+ start_of_dirreq_stats_interval = now;
+
done:
if (open_file)
abort_writing_to_file(open_file);
@@ -1041,29 +1033,46 @@ dump_geoip_stats(void)
tor_free(data_v3);
}
+/** Start time of entry stats. */
+static time_t start_of_entry_stats_interval;
+
+/** Initialize entry stats. */
+void
+geoip_entry_stats_init(time_t now)
+{
+ start_of_entry_stats_interval = now;
+}
+
/** Store all our geoip statistics as entry guards into
* $DATADIR/entry-stats. */
-static void
-dump_entry_stats(void)
+void
+geoip_entry_stats_write(time_t now)
{
-#ifdef ENABLE_ENTRY_STATS
- time_t now = time(NULL);
char *filename = get_datadir_fname("entry-stats");
char *data = NULL;
char written[ISO_TIME_LEN+1];
open_file_t *open_file = NULL;
FILE *out;
- data = geoip_get_client_history(now, GEOIP_CLIENT_CONNECT);
- format_iso_time(written, geoip_get_history_start() + REQUEST_HIST_PERIOD);
+ if (!get_options()->EntryStatistics)
+ goto done;
+
+ /* Discard all items in the client history that are too old. */
+ geoip_remove_old_clients(start_of_entry_stats_interval);
+
+ data = geoip_get_client_history_dirreq(now, GEOIP_CLIENT_CONNECT);
+ format_iso_time(written, now);
out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND,
0600, &open_file);
if (!out)
goto done;
- if (fprintf(out, "entry-stats-end %s (%d s)\nentry-ips %s\n",
- written, REQUEST_HIST_PERIOD, data ? data : "") < 0)
+ if (fprintf(out, "entry-stats-end %s (%u s)\nentry-ips %s\n",
+ written, (unsigned) (now - start_of_entry_stats_interval),
+ data ? data : "") < 0)
goto done;
+ start_of_entry_stats_interval = now;
+
finish_writing_to_file(open_file);
open_file = NULL;
done:
@@ -1071,7 +1080,6 @@ dump_entry_stats(void)
abort_writing_to_file(open_file);
tor_free(filename);
tor_free(data);
-#endif
}
/** Helper used to implement GETINFO ip-to-country/... controller command. */
diff --git a/src/or/main.c b/src/or/main.c
index 403ae93625..16136cb27f 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -830,7 +830,7 @@ run_scheduled_events(time_t now)
static time_t time_to_clean_caches = 0;
static time_t time_to_recheck_bandwidth = 0;
static time_t time_to_check_for_expired_networkstatus = 0;
- static time_t time_to_dump_buffer_stats = 0;
+ static time_t time_to_write_stats_files = 0;
static time_t time_to_retry_dns_init = 0;
or_options_t *options = get_options();
int i;
@@ -958,10 +958,44 @@ run_scheduled_events(time_t now)
time_to_check_for_expired_networkstatus = now + CHECK_EXPIRED_NS_INTERVAL;
}
- if (time_to_dump_buffer_stats < now) {
- if (get_options()->CellStatistics && time_to_dump_buffer_stats)
- dump_buffer_stats();
- time_to_dump_buffer_stats = now + DUMP_BUFFER_STATS_INTERVAL;
+ /* 1g. Check whether we should write statistics to disk.
+ */
+ if (time_to_write_stats_files >= 0 && time_to_write_stats_files < now) {
+#define WRITE_STATS_INTERVAL (24*60*60)
+ or_options_t *options = get_options();
+ if (options->CellStatistics || options->DirReqStatistics ||
+ options->EntryStatistics || options->ExitPortStatistics) {
+ if (!time_to_write_stats_files) {
+ /* Initialize stats. */
+ if (options->CellStatistics)
+ rep_hist_buffer_stats_init(now);
+ if (options->DirReqStatistics)
+ geoip_dirreq_stats_init(now);
+ if (options->EntryStatistics)
+ geoip_entry_stats_init(now);
+ if (options->ExitPortStatistics)
+ rep_hist_exit_stats_init(now);
+ log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
+ "the *-stats files that will first be written to the "
+ "data directory in %d hours from now.",
+ WRITE_STATS_INTERVAL / (60 * 60));
+ time_to_write_stats_files = now + WRITE_STATS_INTERVAL;
+ } else {
+ /* Write stats to disk. */
+ time_to_write_stats_files += WRITE_STATS_INTERVAL;
+ if (options->CellStatistics)
+ rep_hist_buffer_stats_write(time_to_write_stats_files);
+ if (options->DirReqStatistics)
+ geoip_dirreq_stats_write(time_to_write_stats_files);
+ if (options->EntryStatistics)
+ geoip_entry_stats_write(time_to_write_stats_files);
+ if (options->ExitPortStatistics)
+ rep_hist_exit_stats_write(time_to_write_stats_files);
+ }
+ } else {
+ /* Never write stats to disk */
+ time_to_write_stats_files = -1;
+ }
}
/* Remove old information from rephist and the rend cache. */
diff --git a/src/or/or.h b/src/or/or.h
index 9a0f51f461..98ab860a0c 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3739,6 +3739,11 @@ void geoip_start_dirreq(uint64_t dirreq_id, size_t response_size,
void geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type,
dirreq_state_t new_state);
+void geoip_dirreq_stats_init(time_t now);
+void geoip_dirreq_stats_write(time_t now);
+void geoip_entry_stats_init(time_t now);
+void geoip_entry_stats_write(time_t now);
+
/********************************* hibernate.c **********************/
int accounting_parse_options(or_options_t *options, int validate_only);
@@ -4076,11 +4081,11 @@ void rep_hist_note_extend_failed(const char *from_name, const char *to_name);
void rep_hist_dump_stats(time_t now, int severity);
void rep_hist_note_bytes_read(size_t num_bytes, time_t when);
void rep_hist_note_bytes_written(size_t num_bytes, time_t when);
-void rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes,
- time_t now);
-void rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes,
- time_t now);
-void rep_hist_note_exit_stream_opened(uint16_t port, time_t now);
+void rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes);
+void rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes);
+void rep_hist_note_exit_stream_opened(uint16_t port);
+void rep_hist_exit_stats_init(time_t now);
+void rep_hist_exit_stats_write(time_t now);
int rep_hist_bandwidth_assess(void);
char *rep_hist_get_bandwidth_lines(int for_extrainfo);
void rep_hist_update_state(or_state_t *state);
@@ -4132,9 +4137,10 @@ void hs_usage_note_fetch_successful(const char *service_id, time_t now);
void hs_usage_write_statistics_to_file(time_t now);
void hs_usage_free_all(void);
-#define DUMP_BUFFER_STATS_INTERVAL (24*60*60)
-void add_circ_to_buffer_stats(circuit_t *circ, time_t end_of_interval);
-void dump_buffer_stats(void);
+void rep_hist_buffer_stats_init(time_t now);
+void rep_hist_buffer_stats_add_circ(circuit_t *circ,
+ time_t end_of_interval);
+void rep_hist_buffer_stats_write(time_t now);
/********************************* rendclient.c ***************************/
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 3e4ba672d0..44bf940013 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -1321,8 +1321,6 @@ rep_hist_note_bytes_read(size_t num_bytes, time_t when)
}
/* Some constants */
-/** How long are the intervals for measuring exit stats? */
-#define EXIT_STATS_INTERVAL_SEC (24 * 60 * 60)
/** To what multiple should byte numbers be rounded up? */
#define EXIT_STATS_ROUND_UP_BYTES 1024
/** To what multiple should stream counts be rounded up? */
@@ -1344,10 +1342,14 @@ static uint64_t *exit_bytes_written = NULL;
/** Number of streams opened in current period by exit port */
static uint32_t *exit_streams = NULL;
-/** Set up arrays for exit port statistics. */
-static void
-exit_stats_init(void)
+/** When does the current exit stats period end? */
+static time_t start_of_exit_stats_interval;
+
+/** Initialize exit port stats. */
+void
+rep_hist_exit_stats_init(time_t now)
{
+ start_of_exit_stats_interval = now;
exit_bytes_read = tor_malloc_zero(EXIT_STATS_NUM_PORTS *
sizeof(uint64_t));
exit_bytes_written = tor_malloc_zero(EXIT_STATS_NUM_PORTS *
@@ -1356,12 +1358,9 @@ exit_stats_init(void)
sizeof(uint32_t));
}
-/** When does the current exit stats period end? */
-static time_t end_of_current_exit_stats_period = 0;
-
/** Write exit stats for the current period to disk and reset counters. */
-static void
-write_exit_stats(time_t when)
+void
+rep_hist_exit_stats_write(time_t now)
{
char t[ISO_TIME_LEN+1];
int r, i, comma;
@@ -1372,98 +1371,93 @@ write_exit_stats(time_t when)
open_file_t *open_file = NULL;
FILE *out = NULL;
- log_debug(LD_HIST, "Considering writing exit port statistics to disk..");
- if (!exit_bytes_read)
- exit_stats_init();
- while (when > end_of_current_exit_stats_period) {
- format_iso_time(t, end_of_current_exit_stats_period);
- log_info(LD_HIST, "Writing exit port statistics to disk for period "
- "ending at %s.", t);
-
- if (!open_file) {
- out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND,
- 0600, &open_file);
- if (!out) {
- log_warn(LD_HIST, "Couldn't open '%s'.", filename);
- goto done;
- }
- }
+ format_iso_time(t, now);
+ log_info(LD_HIST, "Writing exit port statistics to disk for period "
+ "ending at %s.", t);
- /* written yyyy-mm-dd HH:MM:SS (n s) */
- if (fprintf(out, "exit-stats-end %s (%d s)\n", t,
- EXIT_STATS_INTERVAL_SEC) < 0)
+ if (!open_file) {
+ out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND,
+ 0600, &open_file);
+ if (!out) {
+ log_warn(LD_HIST, "Couldn't open '%s'.", filename);
goto done;
-
- /* Count the total number of bytes, so that we can attribute all
- * observations below a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL
- * of all bytes to a special port 'other'. */
- total_bytes = 0;
- for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
- total_bytes += exit_bytes_read[i];
- total_bytes += exit_bytes_written[i];
- }
- threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL;
-
- /* kibibytes-(read|written) port=kibibytes,.. */
- for (r = 0; r < 2; r++) {
- b = r ? exit_bytes_read : exit_bytes_written;
- tor_assert(b);
- if (fprintf(out, "%s ",
- r ? "exit-kibibytes-read"
- : "exit-kibibytes-written") < 0)
- goto done;
-
- comma = 0;
- other_bytes = 0;
- for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
- if (b[i] > 0) {
- if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) {
- uint64_t num = round_uint64_to_next_multiple_of(b[i],
- EXIT_STATS_ROUND_UP_BYTES);
- num /= 1024;
- if (fprintf(out, "%s%d="U64_FORMAT,
- comma++ ? "," : "", i,
- U64_PRINTF_ARG(num)) < 0)
- goto done;
- } else
- other_bytes += b[i];
- }
- }
- other_bytes = round_uint64_to_next_multiple_of(other_bytes,
- EXIT_STATS_ROUND_UP_BYTES);
- other_bytes /= 1024;
- if (fprintf(out, "%sother="U64_FORMAT"\n",
- comma ? "," : "", U64_PRINTF_ARG(other_bytes))<0)
- goto done;
}
- /* streams-opened port=num,.. */
- if (fprintf(out, "exit-streams-opened ") < 0)
+ }
+
+ /* written yyyy-mm-dd HH:MM:SS (n s) */
+ if (fprintf(out, "exit-stats-end %s (%d s)\n", t,
+ (unsigned) (now - start_of_exit_stats_interval)) < 0)
+ goto done;
+
+ /* Count the total number of bytes, so that we can attribute all
+ * observations below a threshold of 1 / EXIT_STATS_THRESHOLD_RECIPROCAL
+ * of all bytes to a special port 'other'. */
+ total_bytes = 0;
+ for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
+ total_bytes += exit_bytes_read[i];
+ total_bytes += exit_bytes_written[i];
+ }
+ threshold_bytes = total_bytes / EXIT_STATS_THRESHOLD_RECIPROCAL;
+
+ /* exit-kibibytes-(read|written) port=kibibytes,.. */
+ for (r = 0; r < 2; r++) {
+ b = r ? exit_bytes_read : exit_bytes_written;
+ tor_assert(b);
+ if (fprintf(out, "%s ",
+ r ? "exit-kibibytes-read"
+ : "exit-kibibytes-written") < 0)
goto done;
+
comma = 0;
- other_streams = 0;
+ other_bytes = 0;
for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
- if (exit_streams[i] > 0) {
+ if (b[i] > 0) {
if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) {
- uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i],
- EXIT_STATS_ROUND_UP_STREAMS);
- if (fprintf(out, "%s%d=%u",
- comma++ ? "," : "", i, num)<0)
+ uint64_t num = round_uint64_to_next_multiple_of(b[i],
+ EXIT_STATS_ROUND_UP_BYTES);
+ num /= 1024;
+ if (fprintf(out, "%s%d="U64_FORMAT,
+ comma++ ? "," : "", i,
+ U64_PRINTF_ARG(num)) < 0)
goto done;
} else
- other_streams += exit_streams[i];
+ other_bytes += b[i];
}
}
- other_streams = round_uint32_to_next_multiple_of(other_streams,
- EXIT_STATS_ROUND_UP_STREAMS);
- if (fprintf(out, "%sother=%u\n",
- comma ? "," : "", other_streams)<0)
+ other_bytes = round_uint64_to_next_multiple_of(other_bytes,
+ EXIT_STATS_ROUND_UP_BYTES);
+ other_bytes /= 1024;
+ if (fprintf(out, "%sother="U64_FORMAT"\n",
+ comma ? "," : "", U64_PRINTF_ARG(other_bytes))<0)
goto done;
- /* Reset counters */
- memset(exit_bytes_read, 0, sizeof(exit_bytes_read));
- memset(exit_bytes_written, 0, sizeof(exit_bytes_written));
- memset(exit_streams, 0, sizeof(exit_streams));
- end_of_current_exit_stats_period += EXIT_STATS_INTERVAL_SEC;
}
+ /* exit-streams-opened port=num,.. */
+ if (fprintf(out, "exit-streams-opened ") < 0)
+ goto done;
+ comma = 0;
+ other_streams = 0;
+ for (i = 1; i < EXIT_STATS_NUM_PORTS; i++) {
+ if (exit_streams[i] > 0) {
+ if (exit_bytes_read[i] + exit_bytes_written[i] > threshold_bytes) {
+ uint32_t num = round_uint32_to_next_multiple_of(exit_streams[i],
+ EXIT_STATS_ROUND_UP_STREAMS);
+ if (fprintf(out, "%s%d=%u",
+ comma++ ? "," : "", i, num)<0)
+ goto done;
+ } else
+ other_streams += exit_streams[i];
+ }
+ }
+ other_streams = round_uint32_to_next_multiple_of(other_streams,
+ EXIT_STATS_ROUND_UP_STREAMS);
+ if (fprintf(out, "%sother=%u\n",
+ comma ? "," : "", other_streams)<0)
+ goto done;
+ /* Reset counters */
+ memset(exit_bytes_read, 0, sizeof(exit_bytes_read));
+ memset(exit_bytes_written, 0, sizeof(exit_bytes_written));
+ memset(exit_streams, 0, sizeof(exit_streams));
+ start_of_exit_stats_interval = now;
if (open_file)
finish_writing_to_file(open_file);
@@ -1474,59 +1468,36 @@ write_exit_stats(time_t when)
tor_free(filename);
}
-/** Prepare to add an exit stats observation at second <b>when</b> by
- * checking whether this observation lies in the current observation
- * period; if not, shift the current period forward by one until the
- * reported event fits it and write all results in between to disk. */
-static void
-add_exit_obs(time_t when)
-{
- if (!exit_bytes_read)
- exit_stats_init();
- if (when > end_of_current_exit_stats_period) {
- if (end_of_current_exit_stats_period)
- write_exit_stats(when);
- else
- end_of_current_exit_stats_period = when + EXIT_STATS_INTERVAL_SEC;
- }
-}
-
/** Note that we wrote <b>num_bytes</b> to an exit connection to
- * <b>port</b> in second <b>when</b>. */
+ * <b>port</b>. */
void
-rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes,
- time_t when)
+rep_hist_note_exit_bytes_written(uint16_t port, size_t num_bytes)
{
if (!get_options()->ExitPortStatistics)
return;
- add_exit_obs(when);
exit_bytes_written[port] += num_bytes;
log_debug(LD_HIST, "Written %lu bytes to exit connection to port %d.",
(unsigned long)num_bytes, port);
}
/** Note that we read <b>num_bytes</b> from an exit connection to
- * <b>port</b> in second <b>when</b>. */
+ * <b>port</b>. */
void
-rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes,
- time_t when)
+rep_hist_note_exit_bytes_read(uint16_t port, size_t num_bytes)
{
if (!get_options()->ExitPortStatistics)
return;
- add_exit_obs(when);
exit_bytes_read[port] += num_bytes;
log_debug(LD_HIST, "Read %lu bytes from exit connection to port %d.",
(unsigned long)num_bytes, port);
}
-/** Note that we opened an exit stream to <b>port</b> in second
- * <b>when</b>. */
+/** Note that we opened an exit stream to <b>port</b>. */
void
-rep_hist_note_exit_stream_opened(uint16_t port, time_t when)
+rep_hist_note_exit_stream_opened(uint16_t port)
{
if (!get_options()->ExitPortStatistics)
return;
- add_exit_obs(when);
exit_streams[port]++;
log_debug(LD_HIST, "Opened exit stream to port %d", port);
}
@@ -2623,7 +2594,14 @@ hs_usage_write_statistics_to_file(time_t now)
/*** cell statistics ***/
/** Start of the current buffer stats interval. */
-time_t start_of_buffer_stats_interval;
+static time_t start_of_buffer_stats_interval;
+
+/** Initialize buffer stats. */
+void
+rep_hist_buffer_stats_init(time_t now)
+{
+ start_of_buffer_stats_interval = now;
+}
typedef struct circ_buffer_stats_t {
uint32_t processed_cells;
@@ -2639,7 +2617,7 @@ smartlist_t *circuits_for_buffer_stats = NULL;
* <b>end_of_interval</b> and reset cell counters in case the circuit
* remains open in the next measurement interval. */
void
-add_circ_to_buffer_stats(circuit_t *circ, time_t end_of_interval)
+rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval)
{
circ_buffer_stats_t *stat;
time_t start_of_interval;
@@ -2687,9 +2665,8 @@ _buffer_stats_compare_entries(const void **_a, const void **_b)
/** Append buffer statistics to local file. */
void
-dump_buffer_stats(void)
+rep_hist_buffer_stats_write(time_t now)
{
- time_t now = time(NULL);
char *filename;
char written[ISO_TIME_LEN+1];
open_file_t *open_file = NULL;
@@ -2704,7 +2681,7 @@ dump_buffer_stats(void)
circuit_t *circ;
/* add current circuits to stats */
for (circ = _circuit_get_global_list(); circ; circ = circ->next)
- add_circ_to_buffer_stats(circ, now);
+ rep_hist_buffer_stats_add_circ(circ, now);
/* calculate deciles */
memset(processed_cells, 0, SHARES * sizeof(int));
memset(circs_in_share, 0, SHARES * sizeof(int));
@@ -2736,7 +2713,7 @@ dump_buffer_stats(void)
goto done;
format_iso_time(written, now);
if (fprintf(out, "cell-stats-end %s (%d s)\n", written,
- DUMP_BUFFER_STATS_INTERVAL) < 0)
+ (unsigned) (now - start_of_buffer_stats_interval)) < 0)
goto done;
for (i = 0; i < SHARES; i++) {
tor_snprintf(buf, sizeof(buf), "%d", !circs_in_share[i] ? 0 :