diff --git a/changes/ticket5526 b/changes/ticket5526
new file mode 100644
index 0000000000..35911d4b0c
--- /dev/null
+++ b/changes/ticket5526
@@ -0,0 +1,4 @@
+ o Minor features:
+ - Log current accounting state (bytes sent and received + remaining
+ time for the current accounting period) in the server's
+ heartbeat message. Implements ticket 5526; patch from Peter Retzlaff.
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index 22c0f253da..607dec8cd5 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -255,6 +255,13 @@ accounting_get_interval_length(void)
return (int)(interval_end_time - interval_start_time);
}
+/** Return the time at which the current accounting interval will end. */
+time_t
+accounting_get_end_time(void)
+{
+ return interval_end_time;
+}
+
/** Called from main.c to tell us that seconds seconds have
* passed, n_read bytes have been read, and n_written
* bytes have been written. */
diff --git a/src/or/hibernate.h b/src/or/hibernate.h
index 18832fbc6c..4f7331ce8c 100644
--- a/src/or/hibernate.h
+++ b/src/or/hibernate.h
@@ -15,6 +15,7 @@
int accounting_parse_options(const or_options_t *options, int validate_only);
int accounting_is_enabled(const or_options_t *options);
int accounting_get_interval_length(void);
+time_t accounting_get_end_time(void);
void configure_accounting(time_t now);
void accounting_run_housekeeping(time_t now);
void accounting_add_bytes(size_t n_read, size_t n_written, int seconds);
diff --git a/src/or/status.c b/src/or/status.c
index 577587d452..6e2206e5e5 100644
--- a/src/or/status.c
+++ b/src/or/status.c
@@ -15,6 +15,9 @@
#include "circuitlist.h"
#include "main.h"
#include "hibernate.h"
+#include "statefile.h"
+
+static void log_accounting(const time_t now, const or_options_t *options);
/** Return the total number of circuits. */
static int
@@ -111,6 +114,10 @@ log_heartbeat(time_t now)
uptime, count_circuits(),bw_sent,bw_rcvd,
hibernating?" We are currently hibernating.":"");
+ if (server_mode(options) && accounting_is_enabled(options) && !hibernating) {
+ log_accounting(now, options);
+ }
+
if (stats_n_data_cells_packaged && !hibernating)
log_notice(LD_HEARTBEAT, "Average packaged cell fullness: %2.3f%%",
100*(U64_TO_DBL(stats_n_data_bytes_packaged) /
@@ -128,3 +135,27 @@ log_heartbeat(time_t now)
return 0;
}
+static void
+log_accounting(const time_t now, const or_options_t *options)
+{
+ or_state_t *state = get_or_state();
+ char *acc_rcvd = bytes_to_usage(state->AccountingBytesReadInInterval);
+ char *acc_sent = bytes_to_usage(state->AccountingBytesWrittenInInterval);
+ char *acc_max = bytes_to_usage(options->AccountingMax);
+ time_t interval_end = accounting_get_end_time();
+ char end_buf[ISO_TIME_LEN + 1];
+ char *remaining = NULL;
+ format_local_iso_time(end_buf, interval_end);
+ remaining = secs_to_uptime(interval_end - now);
+
+ log_notice(LD_HEARTBEAT, "Heartbeat: Accounting enabled. "
+ "Sent: %s / %s, Received: %s / %s. The "
+ "current accounting interval ends on %s, in %s.",
+ acc_sent, acc_max, acc_rcvd, acc_max, end_buf, remaining);
+
+ tor_free(acc_rcvd);
+ tor_free(acc_sent);
+ tor_free(acc_max);
+ tor_free(remaining);
+}
+