1 /* Copyright (c) 2010-2013, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 * \brief Keep status information and log the heartbeat messages.
12 #include "circuituse.h"
18 #include "circuitlist.h"
21 #include "hibernate.h"
23 #include "statefile.h"
25 static void log_accounting(const time_t now
, const or_options_t
*options
);
27 /** Return the total number of circuits. */
34 TOR_LIST_FOREACH(circ
, circuit_get_global_list(), head
)
40 /** Take seconds <b>secs</b> and return a newly allocated human-readable
43 secs_to_uptime(long secs
)
45 long int days
= secs
/ 86400;
46 int hours
= (int)((secs
- (days
* 86400)) / 3600);
47 int minutes
= (int)((secs
- (days
* 86400) - (hours
* 3600)) / 60);
48 char *uptime_string
= NULL
;
52 tor_asprintf(&uptime_string
, "%d:%02d hours", hours
, minutes
);
55 tor_asprintf(&uptime_string
, "%ld day %d:%02d hours",
56 days
, hours
, minutes
);
59 tor_asprintf(&uptime_string
, "%ld days %d:%02d hours",
60 days
, hours
, minutes
);
67 /** Take <b>bytes</b> and returns a newly allocated human-readable usage
70 bytes_to_usage(uint64_t bytes
)
72 char *bw_string
= NULL
;
74 if (bytes
< (1<<20)) { /* Less than a megabyte. */
75 tor_asprintf(&bw_string
, U64_FORMAT
" kB", U64_PRINTF_ARG(bytes
>>10));
76 } else if (bytes
< (1<<30)) { /* Megabytes. Let's add some precision. */
77 double bw
= U64_TO_DBL(bytes
);
78 tor_asprintf(&bw_string
, "%.2f MB", bw
/(1<<20));
79 } else { /* Gigabytes. */
80 double bw
= U64_TO_DBL(bytes
);
81 tor_asprintf(&bw_string
, "%.2f GB", bw
/(1<<30));
87 /** Log a "heartbeat" message describing Tor's status and history so that the
88 * user can know that there is indeed a running Tor. Return 0 on success and
91 log_heartbeat(time_t now
)
96 const routerinfo_t
*me
;
97 double r
= tls_get_write_overhead_ratio();
98 const int hibernating
= we_are_hibernating();
100 const or_options_t
*options
= get_options();
103 if (public_server_mode(options
) && !hibernating
) {
104 /* Let's check if we are in the current cached consensus. */
105 if (!(me
= router_get_my_routerinfo()))
106 return -1; /* Something stinks, we won't even attempt this. */
108 if (!node_get_by_id(me
->cache_info
.identity_digest
))
109 log_fn(LOG_NOTICE
, LD_HEARTBEAT
, "Heartbeat: It seems like we are not "
110 "in the cached consensus.");
113 uptime
= secs_to_uptime(get_uptime());
114 bw_rcvd
= bytes_to_usage(get_bytes_read());
115 bw_sent
= bytes_to_usage(get_bytes_written());
117 log_fn(LOG_NOTICE
, LD_HEARTBEAT
, "Heartbeat: Tor's uptime is %s, with %d "
118 "circuits open. I've sent %s and received %s.%s",
119 uptime
, count_circuits(),bw_sent
,bw_rcvd
,
120 hibernating
?" We are currently hibernating.":"");
122 if (server_mode(options
) && accounting_is_enabled(options
) && !hibernating
) {
123 log_accounting(now
, options
);
126 if (stats_n_data_cells_packaged
&& !hibernating
)
127 log_notice(LD_HEARTBEAT
, "Average packaged cell fullness: %2.3f%%",
128 100*(U64_TO_DBL(stats_n_data_bytes_packaged
) /
129 U64_TO_DBL(stats_n_data_cells_packaged
*RELAY_PAYLOAD_SIZE
)) );
132 double overhead
= ( r
- 1.0 ) * 100.0;
133 log_notice(LD_HEARTBEAT
, "TLS write overhead: %.f%%", overhead
);
136 if (public_server_mode(options
))
137 rep_hist_log_circuit_handshake_stats(now
);
139 circuit_log_ancient_one_hop_circuits(1800);
149 log_accounting(const time_t now
, const or_options_t
*options
)
151 or_state_t
*state
= get_or_state();
152 char *acc_rcvd
= bytes_to_usage(state
->AccountingBytesReadInInterval
);
153 char *acc_sent
= bytes_to_usage(state
->AccountingBytesWrittenInInterval
);
154 char *acc_max
= bytes_to_usage(options
->AccountingMax
);
155 time_t interval_end
= accounting_get_end_time();
156 char end_buf
[ISO_TIME_LEN
+ 1];
157 char *remaining
= NULL
;
158 format_local_iso_time(end_buf
, interval_end
);
159 remaining
= secs_to_uptime(interval_end
- now
);
161 log_notice(LD_HEARTBEAT
, "Heartbeat: Accounting enabled. "
162 "Sent: %s / %s, Received: %s / %s. The "
163 "current accounting interval ends on %s, in %s.",
164 acc_sent
, acc_max
, acc_rcvd
, acc_max
, end_buf
, remaining
);