summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changes/log_domains12
-rw-r--r--doc/tor.1.txt28
-rw-r--r--src/common/log.c92
-rw-r--r--src/common/torlog.h1
-rw-r--r--src/or/config.c7
-rw-r--r--src/or/or.h3
6 files changed, 127 insertions, 16 deletions
diff --git a/changes/log_domains b/changes/log_domains
new file mode 100644
index 0000000000..7fc0506cdf
--- /dev/null
+++ b/changes/log_domains
@@ -0,0 +1,12 @@
+ o Minor features
+ - Make it simpler to specify "All log domains except for A and B".
+ Previously you needed to say "[*,~A,~B]". Now you can just say
+ "[~A,~B]".
+ - Add a LogMessageDomains option to include the domains of log messages
+ along with the messages. Without this, there's no way to use
+ log domains without reading the source or doing a lot of guessing
+
+ o Documentation
+ - Add documentation for configuring logging at different severities in
+ different log domains. We've had this feature since 0.2.1.1-alpha, but
+ for some reason it never made it into the manpage. Fixes bug 2215.
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index e5dae8cb27..033f0a28e1 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -323,6 +323,34 @@ Other options can be specified either on the command-line (--option
Messages are sent to all the logs that match their severity
level.
+**Log** **[**__domain__,...**]**__minSeverity__[-__maxSeverity__] ... **file** __FILENAME__ +
+
+**Log** **[**__domain__,...**]**__minSeverity__[-__maxSeverity__] ... **stderr**|**stdout**|**syslog** ::
+ As above, but select messages by range of log severity __and__ by a
+ set of "logging domains". Each logging domain corresponds to an area of
+ functionality inside Tor. You can specify any number of severity ranges
+ for a single log statement, each of them prefixed by a comma-separated
+ list of logging domains. You can prefix a domain with ~ to indicate
+ negation, and use * to indicate "all domains". If you specify a severity
+ range without a list of domains, it matches all domains. +
+ +
+ This is an advanced feature which is most useful for debugging one or two
+ of Tor's subsystems at a time. +
+ +
+ The currently recognized domains are: general, crypto, net, config, fs,
+ protocol, mm, http, app, control, circ, rend, bug, dir, dirserv, or, edge,
+ acct, hist, and handshake. Domain names are case-insensitive. +
+ +
+ For example, "`Log [handshake]debug [~net,~mm]info notice stdout`" sends
+ to stdout: all handshake messages of any severity, all info-and-higher
+ messages from domains other than networking and memory management, and all
+ messages of severity notice or higher.
+
+**LogMessageDomains** **0**|**1**::
+ If 1, Tor includes message domains with each log message. Every log
+ message currently has at least one domain; most currently have exactly
+ one. This doesn't affect controller log messages. (Default: 0)
+
**OutboundBindAddress** __IP__::
Make all outbound connections originate from the IP address specified. This
is only useful when you have multiple network interfaces, and you want all
diff --git a/src/common/log.c b/src/common/log.c
index 2fef2cc5d9..cfa0721c27 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -97,6 +97,9 @@ static int log_mutex_initialized = 0;
/** Linked list of logfile_t. */
static logfile_t *logfiles = NULL;
+/** Boolean: do we report logging domains? */
+static int log_domains_are_logged = 0;
+
#ifdef HAVE_SYSLOG_H
/** The number of open syslog log handlers that we have. When this reaches 0,
* we can close our connection to the syslog facility. */
@@ -126,6 +129,9 @@ int _log_global_min_severity = LOG_NOTICE;
static void delete_log(logfile_t *victim);
static void close_log(logfile_t *victim);
+static char *domain_to_string(log_domain_mask_t domain,
+ char *buf, size_t buflen);
+
/** Name of the application: used to generate the message we write at the
* start of each new log. */
static char *appname = NULL;
@@ -217,13 +223,34 @@ format_msg(char *buf, size_t buf_len,
size_t n;
int r;
char *end_of_prefix;
+ char *buf_end;
- assert(buf_len >= 2); /* prevent integer underflow */
+ assert(buf_len >= 16); /* prevent integer underflow and general stupidity */
buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
+ buf_end = buf+buf_len; /* point *after* the last char we can write to */
n = _log_prefix(buf, buf_len, severity);
end_of_prefix = buf+n;
+ if (log_domains_are_logged) {
+ char *cp = buf+n;
+ if (cp == buf_end) goto format_msg_no_room_for_domains;
+ *cp++ = '{';
+ if (cp == buf_end) goto format_msg_no_room_for_domains;
+ cp = domain_to_string(domain, cp, (buf+buf_len-cp));
+ if (cp == buf_end) goto format_msg_no_room_for_domains;
+ *cp++ = '}';
+ if (cp == buf_end) goto format_msg_no_room_for_domains;
+ *cp++ = ' ';
+ if (cp == buf_end) goto format_msg_no_room_for_domains;
+ end_of_prefix = cp;
+ n = cp-buf;
+ format_msg_no_room_for_domains:
+ /* This will leave end_of_prefix and n unchanged, and thus cause
+ * whatever log domain string we had written to be clobbered. */
+ ;
+ }
+
if (funcname && should_log_function_name(domain, severity)) {
r = tor_snprintf(buf+n, buf_len-n, "%s(): ", funcname);
if (r<0)
@@ -305,6 +332,7 @@ logv(int severity, log_domain_mask_t domain, const char *funcname,
&msg_len);
formatted = 1;
}
+
if (lf->is_syslog) {
#ifdef HAVE_SYSLOG_H
char *m = end_of_prefix;
@@ -563,8 +591,7 @@ add_stream_log_impl(const log_severity_list_t *severity,
* to <b>fd</b>. Steals a reference to <b>severity</b>; the caller must
* not use it after calling this function. */
void
-add_stream_log(const log_severity_list_t *severity,
- const char *name, int fd)
+add_stream_log(const log_severity_list_t *severity, const char *name, int fd)
{
LOCK_LOGS();
add_stream_log_impl(severity, name, fd);
@@ -583,6 +610,16 @@ init_logging(void)
pending_cb_messages = smartlist_create();
}
+/** Set whether we report logging domains as a part of our log messages.
+ */
+void
+logs_set_domain_logging(int enabled)
+{
+ LOCK_LOGS();
+ log_domains_are_logged = enabled;
+ UNLOCK_LOGS();
+}
+
/** Add a log handler to receive messages during startup (before the real
* logs are initialized).
*/
@@ -775,7 +812,6 @@ add_syslog_log(const log_severity_list_t *severity)
lf->fd = -1;
lf->severities = tor_memdup(severity, sizeof(log_severity_list_t));
lf->filename = tor_strdup("<syslog>");
-
lf->is_syslog = 1;
LOCK_LOGS();
@@ -832,18 +868,41 @@ parse_log_domain(const char *domain)
}
return 0;
}
-#if 0
-/** Translate a bitmask of log domains to a string, or NULL if the bitmask
- * is undecodable. */
-static const char *
-domain_to_string(log_domain_mask_t domain)
+
+/** Translate a bitmask of log domains to a string. */
+static char *
+domain_to_string(log_domain_mask_t domain, char *buf, size_t buflen)
{
- int bit = tor_log2(domain);
- if ((bit == 0 && domain == 0) || bit >= N_LOGGING_DOMAINS)
- return NULL;
- return domain_list[bit];
+ char *cp = buf;
+ char *eos = buf+buflen;
+
+ buf[0] = '\0';
+ if (! domain)
+ return buf;
+ while (1) {
+ const char *d;
+ int bit = tor_log2(domain);
+ size_t n;
+ if (bit >= N_LOGGING_DOMAINS) {
+ tor_snprintf(buf, buflen, "<BUG:Unknown domain %lx>", (long)domain);
+ return buf+strlen(buf);
+ }
+ d = domain_list[bit];
+ n = strlcpy(cp, d, eos-cp);
+ if (n >= buflen) {
+ tor_snprintf(buf, buflen, "<BUG:Truncating domain %lx>", (long)domain);
+ return buf+strlen(buf);
+ }
+ cp += n;
+ domain &= ~(1<<bit);
+
+ if (domain == 0 || (eos-cp) < 2)
+ return cp;
+
+ memcpy(cp, ",", 2); /*Nul-terminated ,"*/
+ cp++;
+ }
}
-#endif
/** Parse a log severity pattern in *<b>cfg_ptr</b>. Advance cfg_ptr after
* the end of the severityPattern. Set the value of <b>severity_out</b> to
@@ -919,7 +978,10 @@ parse_log_severity_config(const char **cfg_ptr,
smartlist_free(domains_list);
if (err)
return -1;
- domains &= ~neg_domains;
+ if (domains == 0 && neg_domains)
+ domains = ~neg_domains;
+ else
+ domains &= ~neg_domains;
cfg = eat_whitespace(closebracket+1);
} else {
++got_an_unqualified_range;
diff --git a/src/common/torlog.h b/src/common/torlog.h
index f0be732270..791e363946 100644
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@ -132,6 +132,7 @@ int add_file_log(const log_severity_list_t *severity, const char *filename);
int add_syslog_log(const log_severity_list_t *severity);
#endif
int add_callback_log(const log_severity_list_t *severity, log_callback cb);
+void logs_set_domain_logging(int enabled);
int get_min_log_level(void);
void switch_logs_debug(void);
void logs_free_all(void);
diff --git a/src/or/config.c b/src/or/config.c
index ec86dbca56..178ed1e385 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -288,6 +288,7 @@ static config_var_t _option_vars[] = {
OBSOLETE("IgnoreVersion"),
V(KeepalivePeriod, INTERVAL, "5 minutes"),
VAR("Log", LINELIST, Logs, NULL),
+ V(LogMessageDomains, BOOL, "0"),
OBSOLETE("LinkPadding"),
OBSOLETE("LogLevel"),
OBSOLETE("LogFile"),
@@ -3817,7 +3818,8 @@ options_transition_affects_workers(or_options_t *old_options,
old_options->SafeLogging != new_options->SafeLogging ||
old_options->ClientOnly != new_options->ClientOnly ||
public_server_mode(old_options) != public_server_mode(new_options) ||
- !config_lines_eq(old_options->Logs, new_options->Logs))
+ !config_lines_eq(old_options->Logs, new_options->Logs) ||
+ old_options->LogMessageDomains != new_options->LogMessageDomains)
return 1;
/* Check whether log options match. */
@@ -4393,6 +4395,9 @@ options_init_logs(or_options_t *options, int validate_only)
}
smartlist_free(elts);
+ if (ok && !validate_only)
+ logs_set_domain_logging(options->LogMessageDomains);
+
return ok?0:-1;
}
diff --git a/src/or/or.h b/src/or/or.h
index 752de219ef..2a55668404 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2345,6 +2345,9 @@ typedef struct {
config_line_t *Logs; /**< New-style list of configuration lines
* for logs */
+ int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which
+ * each log message occurs? */
+
char *DebugLogFile; /**< Where to send verbose log messages. */
char *DataDirectory; /**< OR only: where to store long-term data. */
char *Nickname; /**< OR only: nickname of this onion router. */