mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
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
This commit is contained in:
parent
c09de55fb8
commit
7711c2e745
115
src/common/log.c
115
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;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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[201];
|
||||
time_t t;
|
||||
struct timeval now;
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user