diff options
-rwxr-xr-x | asterisk.h | 2 | ||||
-rwxr-xr-x | configs/logger.conf.sample | 16 | ||||
-rwxr-xr-x | loader.c | 4 | ||||
-rwxr-xr-x | logger.c | 165 |
4 files changed, 182 insertions, 5 deletions
diff --git a/asterisk.h b/asterisk.h index 34dae49c8..07106fbf6 100755 --- a/asterisk.h +++ b/asterisk.h @@ -38,4 +38,6 @@ extern int load_pbx(void); extern int init_logger(void); /* Provided by frame.c */ extern int init_framer(void); +/* Provided by logger.c */ +extern int reload_logger(void); #endif diff --git a/configs/logger.conf.sample b/configs/logger.conf.sample new file mode 100755 index 000000000..d773ad693 --- /dev/null +++ b/configs/logger.conf.sample @@ -0,0 +1,16 @@ +; +; Logging Configuration +; +[logfiles] +; +; Format is "filename" and then "levels" of debugging to be included: +; debug +; notice +; warning +; error +; +; Special filename "console" represents the system console +; +;debug => debug +console => notice,warning,error +messages => notice,warning,error @@ -135,6 +135,10 @@ int ast_unload_resource(char *resource_name, int force) void ast_module_reload(void) { struct module *m; + + /* We'll do the logger the favor of calling its reload here first */ + + ast_pthread_mutex_lock(&modlock); m = module_list; while(m) { @@ -1,9 +1,9 @@ /* - * Cheops Next Generation + * Asterisk Logger * * Mark Spencer <markster@marko.net> * - * Copyright(C)1999, Mark Spencer + * Copyright(C)1999, Linux Support Services, Inc. * * Distributed under the terms of the GNU General Public License (GPL) Version 2 * @@ -18,6 +18,7 @@ #include <asterisk/logger.h> #include <asterisk/options.h> #include <asterisk/channel.h> +#include <asterisk/config.h> #include <string.h> #include <stdlib.h> #include <errno.h> @@ -37,6 +38,15 @@ static struct msglist { struct msglist *next; } *list = NULL, *last = NULL; +struct logfile { + char fn[256]; + int logflags; + FILE *f; + struct logfile *next; +}; + +static struct logfile *logfiles = NULL; + static int msgcnt = 0; static FILE *eventlog = NULL; @@ -49,6 +59,108 @@ static char *levels[] = { "ERROR" }; +static int make_components(char *s, int lineno) +{ + char *w; + int res = 0; + w = strtok(s, ","); + while(w) { + while(*w && (*w < 33)) + w++; + if (!strcasecmp(w, "debug")) + res |= (1 << 0); + else if (!strcasecmp(w, "notice")) + res |= (1 << 2); + else if (!strcasecmp(w, "warning")) + res |= (1 << 3); + else if (!strcasecmp(w, "error")) + res |= (1 << 4); + else { + fprintf(stderr, "Logfile Warning: Unknown keyword '%s' at line %d of logger.conf\n", w, lineno); + } + w = strtok(NULL, ","); + } + return res; +} + +static struct logfile *make_logfile(char *fn, char *components, int lineno) +{ + struct logfile *f; + char tmp[256]; + if (!strlen(fn)) + return NULL; + f = malloc(sizeof(struct logfile)); + if (f) { + memset(f, 0, sizeof(f)); + strncpy(f->fn, fn, sizeof(f->fn) - 1); + if (!strcasecmp(fn, "ignore")) { + f->f = NULL; + } else if (!strcasecmp(fn, "console")) { + f->f = stdout; + } else { + if (fn[0] == '/') + strncpy(tmp, fn, sizeof(tmp) - 1); + else + snprintf(tmp, sizeof(tmp), "%s/%s", AST_LOG_DIR, fn); + f->f = fopen(tmp, "a"); + if (!f->f) { + /* Can't log here, since we're called with a lock */ + fprintf(stderr, "Logger Warning: Unable to open log file '%s': %s\n", tmp, strerror(errno)); + } + } + f->logflags = make_components(components, lineno); + + } + return f; +} + +static void init_logger_chain(void) +{ + struct logfile *f, *cur; + struct ast_config *cfg; + struct ast_variable *var; + + ast_pthread_mutex_lock(&loglock); + + /* Free anything that is here */ + f = logfiles; + while(f) { + cur = f->next; + if (f->f && (f->f != stdout) && (f->f != stderr)) + fclose(f->f); + free(f); + f = cur; + } + + logfiles = NULL; + + ast_pthread_mutex_unlock(&loglock); + cfg = ast_load("logger.conf"); + ast_pthread_mutex_lock(&loglock); + + /* If no config file, we're fine */ + if (!cfg) { + ast_pthread_mutex_unlock(&loglock); + return; + } + var = ast_variable_browse(cfg, "logfiles"); + while(var) { + f = make_logfile(var->name, var->value, var->lineno); + if (f) { + f->next = logfiles; + logfiles = f; + } + var = var->next; + } + if (!logfiles) { + /* Gotta have at least one. We'll make a NULL one */ + logfiles = make_logfile("ignore", "", -1); + } + ast_pthread_mutex_unlock(&loglock); + + +} + static struct verb { void (*verboser)(char *string, int opos, int replacelast, int complete); struct verb *next; @@ -60,12 +172,35 @@ int init_logger(void) mkdir(AST_LOG_DIR, 0755); eventlog = fopen(AST_EVENT_LOG, "a"); if (eventlog) { + init_logger_chain(); ast_log(LOG_EVENT, "Started Asterisk Event Logger\n"); if (option_verbose) ast_verbose("Asterisk Event Logger Started\n"); return 0; } else ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno)); + init_logger_chain(); + return -1; +} + +int reload_logger(void) +{ + ast_pthread_mutex_lock(&loglock); + if (eventlog) + fclose(eventlog); + mkdir(AST_LOG_DIR, 0755); + eventlog = fopen(AST_EVENT_LOG, "a"); + ast_pthread_mutex_unlock(&loglock); + + if (eventlog) { + init_logger_chain(); + ast_log(LOG_EVENT, "Restarted Asterisk Event Logger\n"); + if (option_verbose) + ast_verbose("Asterisk Event Logger restarted\n"); + return 0; + } else + ast_log(LOG_ERROR, "Unable to create event log: %s\n", strerror(errno)); + init_logger_chain(); return -1; } @@ -74,6 +209,7 @@ extern void ast_log(int level, char *file, int line, char *function, char *fmt, char date[256]; time_t t; struct tm *tm; + struct logfile *f; va_list ap; va_start(ap, fmt); @@ -92,9 +228,28 @@ extern void ast_log(int level, char *file, int line, char *function, char *fmt, } else ast_log(LOG_WARNING, "Unable to retrieve local time?\n"); } else { - fprintf(stdout, "%s[%ld]: File %s, Line %d (%s): ", levels[level], pthread_self(), file, line, function); - vfprintf(stdout, fmt, ap); - fflush(stdout); + if (logfiles) { + f = logfiles; + while(f) { + if (f->logflags & (1 << level) && f->f) { + if ((f->f != stdout) && (f->f != stderr)) { + time(&t); + tm = localtime(&t); + strftime(date, sizeof(date), "%b %e %T", tm); + fprintf(f->f, "%s %s[%ld]: File %s, Line %d (%s): ", date, levels[level], pthread_self(), file, line, function); + } else { + fprintf(f->f, "%s[%ld]: File %s, Line %d (%s): ", levels[level], pthread_self(), file, line, function); + } + vfprintf(f->f, fmt, ap); + fflush(f->f); + } + f = f->next; + } + } else { + fprintf(stdout, "%s[%ld]: File %s, Line %d (%s): ", levels[level], pthread_self(), file, line, function); + vfprintf(stdout, fmt, ap); + fflush(stdout); + } } ast_pthread_mutex_unlock(&loglock); va_end(ap); |