aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2003-09-16 17:58:36 +0000
committerNick Mathewson <nickm@torproject.org>2003-09-16 17:58:36 +0000
commit7711c2e7457576084da7d68913573cafde87d853 (patch)
tree57fdb8e4a5be9b9588dc13bce3e5b162ed0393b3
parentc09de55fb843c2875caf59cc6447f184d51ce209 (diff)
downloadtor-7711c2e7457576084da7d68913573cafde87d853.tar.gz
tor-7711c2e7457576084da7d68913573cafde87d853.zip
Add backend support for multiple logfiles, including console logs.
Also optimize logging by formatting messages in memory before sending them through stdio. (It turns out (according to gprof) that logging performance matters.) svn:r463
-rw-r--r--src/common/log.c115
-rw-r--r--src/common/log.h5
2 files changed, 108 insertions, 12 deletions
diff --git a/src/common/log.c b/src/common/log.c
index f38089a40f..c4a5e683c9 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -5,7 +5,18 @@
#include "../or/or.h"
#include "util.h"
-static const char *sev_to_string(int severity) {
+struct logfile_t;
+
+typedef struct logfile_t {
+ struct logfile_t *next;
+ const char *filename;
+ FILE *file;
+ int needs_close;
+ int loglevel;
+ int max_loglevel;
+} logfile_t;
+
+static INLINE const char *sev_to_string(int severity) {
switch(severity) {
case LOG_DEBUG: return "debug";
case LOG_INFO: return "info";
@@ -20,26 +31,63 @@ static const char *sev_to_string(int severity) {
}
static int loglevel = LOG_DEBUG;
+static logfile_t *logfiles = NULL;
-static void
-logv(int severity, const char *funcname, const char *format, va_list ap)
+/* Format a log message into a fixed-sized buffer. (This is factored out
+ * of 'logv' so that we never format a message more than once.
+ */
+static INLINE void format_msg(char *buf, size_t buf_len,
+ int severity, const char *funcname,
+ const char *format, va_list ap)
{
- char buf[201];
time_t t;
struct timeval now;
+ int n;
+
+ buf_len -= 2; /* subtract 2 characters so we have room for \n\0 */
+
+ my_gettimeofday(&now);
+ t = (time_t)now.tv_sec;
+
+ n = strftime(buf, buf_len, "%b %d %H:%M:%S", localtime(&t));
+ n += snprintf(buf+n, buf_len-n,
+ ".%.3ld [%s] ",
+ (long)now.tv_usec / 1000, sev_to_string(severity));
+ if (funcname)
+ n += snprintf(buf+n, buf_len-n, "%s(): ", funcname);
+
+ n += vsnprintf(buf+n,buf_len-n,format,ap);
+ buf[n]='\n';
+ buf[n+1]='\0';
+}
+
+static void
+logv(int severity, const char *funcname, const char *format, va_list ap)
+{
+ char buf[1024];
+ int formatted = 0;
+ logfile_t *lf;
assert(format);
if (severity < loglevel)
return;
- my_gettimeofday(&now);
+ if (!logfiles) {
+ /* XXX This is a temporary measure until we get configuration support
+ for logfiles. */
+ add_stream_log(loglevel, "<stdout>", stdout);
+ }
+ for (lf = logfiles; lf; lf = lf->next) {
+ if (severity < lf->loglevel || severity > lf->max_loglevel)
+ continue;
+ if (!lf->file)
+ continue;
- t = time(NULL);
- strftime(buf, 200, "%b %d %H:%M:%S", localtime(&t));
- printf("%s.%.3ld [%s] ", buf, (long)now.tv_usec / 1000, sev_to_string(severity));
- if (funcname)
- printf("%s(): ", funcname);
- vprintf(format,ap);
- printf("\n");
+ if (!formatted) {
+ format_msg(buf, 1024, severity, funcname, format, ap);
+ formatted = 1;
+ }
+ fputs(buf, lf->file);
+ }
}
void
@@ -65,4 +113,47 @@ void _log_fn(int severity, const char *fn, const char *format, ...)
va_end(ap);
}
+void close_logs()
+{
+ logfile_t *next, *lf;
+ for (lf = logfiles; lf; lf = lf->next) {
+ if (lf->needs_close)
+ fclose(lf->file);
+ next = lf->next;
+ free(lf);
+ }
+ logfiles = NULL;
+}
+void reset_logs()
+{
+ logfile_t *lf;
+ for (lf = logfiles; lf; lf = lf->next) {
+ if (lf->needs_close) {
+ fclose(lf->file);
+ lf->file = fopen(lf->filename, "a");
+ }
+ }
+}
+
+void add_stream_log(int loglevel, const char *name, FILE *stream)
+{
+ logfile_t *lf;
+ lf = tor_malloc(sizeof(logfile_t));
+ lf->filename = name;
+ lf->needs_close = 0;
+ lf->loglevel = loglevel;
+ lf->max_loglevel = LOG_EMERG;
+ lf->file = stream;
+ lf->next = logfiles;
+ logfiles = lf;
+}
+
+void add_file_log(int loglevel, const char *filename)
+{
+ FILE *f;
+ f = fopen(filename, "a");
+ if (!f) return;
+ add_stream_log(loglevel, filename, f);
+ logfiles->needs_close = 1;
+}
diff --git a/src/common/log.h b/src/common/log.h
index 38f330c081..9b9d072eec 100644
--- a/src/common/log.h
+++ b/src/common/log.h
@@ -30,6 +30,11 @@
void log_set_severity(int severity);
+void add_stream_log(int loglevel, const char *name, FILE *stream);
+void add_file_log(int severity, const char *filename);
+void close_logs();
+void reset_logs();
+
/* Outputs a message to stdout */
void log(int severity, const char *format, ...) CHECK_PRINTF(2,3);