Well, I know this is a REALLY old thread, but I found myself in desperate need of this feature, so I manually applied this patch to 1.2.14 . It compiles fine, and but I have yet to test it in production. Preliminary results show that it appears to be working, in the sense that it logs the restarts to database. I will be testing this more over the next couple of days, and I expect it to be on a production server right away. I’ll post the results. This needs to be a feature in Asterisk. This works, but it is a bit of a hack(no offense to the author) it just isn’t appropriate to be logging from the queue to logger. It needs to be structure more like the CDR facility. If Asterisk is to be used in large installations, this is critical information. I wish I had the time to fix it up right. I’m sure a lot of users feel the same way. It doesn’t appear to have changed in 1.4… Oh well.
diff -urNp asterisk-1.2.13/logger.c asterisk-queue-log-mysql/logger.c
--- asterisk-1.2.13/logger.c 2006-09-06 20:14:14.000000000 -0600
+++ asterisk-queue-log-mysql/logger.c 2006-12-03 22:21:39.000000000 -0700
@@ -18,7 +18,7 @@
/*! \file
* \brief Asterisk Logger
- *
+ *
* Logging routines
*
*/
@@ -32,6 +32,7 @@
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
+#include <mysql.h>
#define SYSLOG_NAMES /* so we can map syslog facilities names to their numeric values,
from <syslog.h> which is included by logger.h */
@@ -78,6 +79,18 @@ static int syslog_level_map[] = {
static char dateformat[256] = "%b %e %T"; /* Original Asterisk Format */
+
+static MYSQL logdb;
+static char my_hostname[100];
+static char my_dbname[100];
+static char my_table[100];
+static char my_password[100];
+static char my_user[100];
+static unsigned int my_port;
+static char my_sock[100];
+static int use_mysql;
+
+
AST_MUTEX_DEFINE_STATIC(msglist_lock);
AST_MUTEX_DEFINE_STATIC(loglock);
static int filesize_reload_needed = 0;
@@ -148,7 +161,7 @@ static int make_components(char *s, int
while(w) {
while(*w && (*w < 33))
w++;
- if (!strcasecmp(w, "error"))
+ if (!strcasecmp(w, "error"))
res |= (1 << __LOG_ERROR);
else if (!strcasecmp(w, "warning"))
res |= (1 << __LOG_WARNING);
@@ -214,41 +227,41 @@ static struct logchannel *make_logchanne
}
#else
chan->facility = -1;
- if (!strcasecmp(facility, "kern"))
+ if (!strcasecmp(facility, "kern"))
chan->facility = LOG_KERN;
- else if (!strcasecmp(facility, "USER"))
+ else if (!strcasecmp(facility, "USER"))
chan->facility = LOG_USER;
- else if (!strcasecmp(facility, "MAIL"))
+ else if (!strcasecmp(facility, "MAIL"))
chan->facility = LOG_MAIL;
- else if (!strcasecmp(facility, "DAEMON"))
+ else if (!strcasecmp(facility, "DAEMON"))
chan->facility = LOG_DAEMON;
- else if (!strcasecmp(facility, "AUTH"))
+ else if (!strcasecmp(facility, "AUTH"))
chan->facility = LOG_AUTH;
- else if (!strcasecmp(facility, "SYSLOG"))
+ else if (!strcasecmp(facility, "SYSLOG"))
chan->facility = LOG_SYSLOG;
- else if (!strcasecmp(facility, "LPR"))
+ else if (!strcasecmp(facility, "LPR"))
chan->facility = LOG_LPR;
- else if (!strcasecmp(facility, "NEWS"))
+ else if (!strcasecmp(facility, "NEWS"))
chan->facility = LOG_NEWS;
- else if (!strcasecmp(facility, "UUCP"))
+ else if (!strcasecmp(facility, "UUCP"))
chan->facility = LOG_UUCP;
- else if (!strcasecmp(facility, "CRON"))
+ else if (!strcasecmp(facility, "CRON"))
chan->facility = LOG_CRON;
- else if (!strcasecmp(facility, "LOCAL0"))
+ else if (!strcasecmp(facility, "LOCAL0"))
chan->facility = LOG_LOCAL0;
- else if (!strcasecmp(facility, "LOCAL1"))
+ else if (!strcasecmp(facility, "LOCAL1"))
chan->facility = LOG_LOCAL1;
- else if (!strcasecmp(facility, "LOCAL2"))
+ else if (!strcasecmp(facility, "LOCAL2"))
chan->facility = LOG_LOCAL2;
- else if (!strcasecmp(facility, "LOCAL3"))
+ else if (!strcasecmp(facility, "LOCAL3"))
chan->facility = LOG_LOCAL3;
- else if (!strcasecmp(facility, "LOCAL4"))
+ else if (!strcasecmp(facility, "LOCAL4"))
chan->facility = LOG_LOCAL4;
- else if (!strcasecmp(facility, "LOCAL5"))
+ else if (!strcasecmp(facility, "LOCAL5"))
chan->facility = LOG_LOCAL5;
- else if (!strcasecmp(facility, "LOCAL6"))
+ else if (!strcasecmp(facility, "LOCAL6"))
chan->facility = LOG_LOCAL6;
- else if (!strcasecmp(facility, "LOCAL7"))
+ else if (!strcasecmp(facility, "LOCAL7"))
chan->facility = LOG_LOCAL7;
#endif /* Solaris */
@@ -263,13 +276,13 @@ static struct logchannel *make_logchanne
openlog("asterisk", LOG_PID, chan->facility);
} else {
if (channel[0] == '/') {
- if(!ast_strlen_zero(hostname)) {
+ if(!ast_strlen_zero(hostname)) {
snprintf(chan->filename, sizeof(chan->filename) - 1,"%s.%s", channel, hostname);
} else {
ast_copy_string(chan->filename, channel, sizeof(chan->filename));
}
- }
-
+ }
+
if(!ast_strlen_zero(hostname)) {
snprintf(chan->filename, sizeof(chan->filename), "%s/%s.%s",(char *)ast_config_AST_LOG_DIR, channel, hostname);
} else {
@@ -279,7 +292,7 @@ static struct logchannel *make_logchanne
if (!chan->fileptr) {
/* Can't log here, since we're called with a lock */
fprintf(stderr, "Logger Warning: Unable to open log file '%s': %s\n", chan->filename, strerror(errno));
- }
+ }
chan->type = LOGTYPE_FILE;
}
chan->logmask = make_components(components, lineno);
@@ -303,14 +316,14 @@ static void init_logger_chain(void)
}
logchannels = NULL;
ast_mutex_unlock(&loglock);
-
+
global_logmask = 0;
errno = 0;
/* close syslog */
closelog();
-
+
cfg = ast_config_load("logger.conf");
-
+
/* If no config file, we're fine, set default options. */
if (!cfg) {
if (errno)
@@ -326,7 +339,7 @@ static void init_logger_chain(void)
global_logmask |= chan->logmask;
return;
}
-
+
ast_mutex_lock(&loglock);
if ((s = ast_variable_retrieve(cfg, "general", "appendhostname"))) {
if(ast_true(s)) {
@@ -349,6 +362,36 @@ static void init_logger_chain(void)
logfiles.event_log = ast_true(s);
}
+ if ((s = ast_variable_retrieve(cfg, "mysql", "hostname"))) {
+ ast_copy_string(my_hostname, s, sizeof(my_hostname));
+ }
+ if ((s = ast_variable_retrieve(cfg, "mysql", "dbname"))) {
+ ast_copy_string(my_dbname, s, sizeof(my_dbname));
+ }
+ if ((s = ast_variable_retrieve(cfg, "mysql", "table"))) {
+ ast_copy_string(my_table, s, sizeof(my_table));
+ }
+ if ((s = ast_variable_retrieve(cfg, "mysql", "password"))) {
+ ast_copy_string(my_password, s, sizeof(my_password));
+ }
+ if ((s = ast_variable_retrieve(cfg, "mysql", "user"))) {
+ ast_copy_string(my_user, s, sizeof(my_user));
+ }
+ if ((s = ast_variable_retrieve(cfg, "mysql", "port"))) {
+ if (sscanf(s, "%d", &my_port) < 1) {
+ my_port = 0;
+ }
+ }
+ if ((s = ast_variable_retrieve(cfg, "mysql", "sock"))) {
+ ast_copy_string(my_sock, s, sizeof(my_sock));
+ }
+ if(!mysql_real_connect(&logdb, my_hostname, my_user, my_password, my_dbname, my_port, my_sock, 0)){
+ ast_log(LOG_ERROR, "Failed to connect to mysql database %s on %s.\n", my_dbname, my_hostname);
+ use_mysql = 0;
+ } else {
+ use_mysql = 1;
+ }
+
var = ast_variable_browse(cfg, "logfiles");
while(var) {
chan = make_logchannel(var->name, var->value, var->lineno);
@@ -372,7 +415,50 @@ void ast_queue_log(const char *queuename
va_start(ap, fmt);
fprintf(qlog, "%ld|%s|%s|%s|%s|", (long)time(NULL), callid, queuename, agent, event);
vfprintf(qlog, fmt, ap);
- fprintf(qlog, "\n");
+ fprintf(qlog, "\n");
+
+ if(use_mysql == 1) {
+ char *myquery = malloc(500);
+ char *myquery_ap = malloc(100);
+ char *myfmt = malloc(strlen(fmt)*3+1>8?strlen(fmt)*3+1:9);
+ int x,y;
+ int fmt_count = 0;
+ int len = 500;
+
+ if(snprintf(myquery, 500, "insert into %s(time,callid,queuename,agent,event,arg1,arg2,arg3) values(from_unixtime(%ld),'%s','%s','%s','%s',", my_table, (long)time(NULL), callid, queuename, agent, event)<500) {
+ len = 500 - strlen(myquery);
+ myfmt[0] = '\'';
+ for(x=0,y=0; x<strlen(fmt); x++) {
+ if(fmt[x] == '|') {
+ myfmt[++y] = '\'';
+ myfmt[++y] = ',';
+ myfmt[++y] = '\'';
+ fmt_count ++;
+ } else {
+ myfmt[++y] = fmt[x];
+ }
+ }
+ for(;fmt_count<2; fmt_count++) {
+ myfmt[++y] = '\'';
+ myfmt[++y] = ',';
+ myfmt[++y] = '\'';
+ }
+ myfmt[++y] = '\'';
+ myfmt[++y] = 0;
+ if(vsnprintf(myquery_ap, 100, myfmt, ap)<100) {
+ strncat(myquery, myquery_ap, len-1);
+ len = 500 - strlen(myquery);
+ strncat(myquery, ")", len-1);
+ if(mysql_real_query(&logdb, myquery, strlen(myquery)+1)){
+ printf(mysql_error(&logdb));
+ }
+ }
+ }
+ free(myfmt);
+ free(myquery_ap);
+ free(myquery);
+ }
+
va_end(ap);
fflush(qlog);
}
@@ -390,15 +476,15 @@ int reload_logger(int rotate)
ast_mutex_lock(&msglist_lock); /* to avoid deadlock */
ast_mutex_lock(&loglock);
- if (eventlog)
+ if (eventlog)
fclose(eventlog);
- else
+ else
event_rotate = 0;
eventlog = NULL;
- if (qlog)
+ if (qlog)
fclose(qlog);
- else
+ else
queue_rotate = 0;
qlog = NULL;
@@ -415,7 +501,7 @@ int reload_logger(int rotate)
f->fileptr = NULL;
if(rotate) {
ast_copy_string(old, f->filename, sizeof(old));
-
+
for(x=0;;x++) {
snprintf(new, sizeof(new), "%s.%d", f->filename, x);
myf = fopen((char *)new, "r");
@@ -425,7 +511,7 @@ int reload_logger(int rotate)
break;
}
}
-
+
/* do it */
if (rename(old,new))
fprintf(stderr, "Unable to rename file '%s' to '%s'\n", old, new);
@@ -449,7 +535,7 @@ int reload_logger(int rotate)
else
break;
}
-
+
/* do it */
if (rename(old,new))
ast_log(LOG_ERROR, "Unable to rename file '%s' to '%s'\n", old, new);
@@ -477,7 +563,7 @@ int reload_logger(int rotate)
else
break;
}
-
+
/* do it */
if (rename(old, new))
ast_log(LOG_ERROR, "Unable to rename file '%s' to '%s'\n", old, new);
@@ -518,7 +604,7 @@ static int handle_logger_rotate(int fd,
return RESULT_SUCCESS;
}
-/*--- handle_logger_show_channels: CLI command to show logging system
+/*--- handle_logger_show_channels: CLI command to show logging system
configuration */
static int handle_logger_show_channels(int fd, int argc, char *argv[])
{
@@ -536,19 +622,19 @@ static int handle_logger_show_channels(i
ast_cli(fd, FORMATL, chan->filename, chan->type==LOGTYPE_CONSOLE ? "Console" : (chan->type==LOGTYPE_SYSLOG ? "Syslog" : "File"),
chan->disabled ? "Disabled" : "Enabled");
ast_cli(fd, " - ");
- if (chan->logmask & (1 << __LOG_DEBUG))
+ if (chan->logmask & (1 << __LOG_DEBUG))
ast_cli(fd, "Debug ");
- if (chan->logmask & (1 << __LOG_DTMF))
+ if (chan->logmask & (1 << __LOG_DTMF))
ast_cli(fd, "DTMF ");
- if (chan->logmask & (1 << __LOG_VERBOSE))
+ if (chan->logmask & (1 << __LOG_VERBOSE))
ast_cli(fd, "Verbose ");
- if (chan->logmask & (1 << __LOG_WARNING))
+ if (chan->logmask & (1 << __LOG_WARNING))
ast_cli(fd, "Warning ");
- if (chan->logmask & (1 << __LOG_NOTICE))
+ if (chan->logmask & (1 << __LOG_NOTICE))
ast_cli(fd, "Notice ");
- if (chan->logmask & (1 << __LOG_ERROR))
+ if (chan->logmask & (1 << __LOG_ERROR))
ast_cli(fd, "Error ");
- if (chan->logmask & (1 << __LOG_EVENT))
+ if (chan->logmask & (1 << __LOG_EVENT))
ast_cli(fd, "Event ");
ast_cli(fd, "\n");
chan = chan->next;
@@ -556,7 +642,7 @@ static int handle_logger_show_channels(i
ast_cli(fd, "\n");
ast_mutex_unlock(&loglock);
-
+
return RESULT_SUCCESS;
}
@@ -578,22 +664,22 @@ static char logger_show_channels_help[]
"Usage: logger show channels\n"
" Show configured logger channels.\n";
-static struct ast_cli_entry logger_show_channels_cli =
- { { "logger", "show", "channels", NULL },
+static struct ast_cli_entry logger_show_channels_cli =
+ { { "logger", "show", "channels", NULL },
handle_logger_show_channels, "List configured log channels",
logger_show_channels_help };
-static struct ast_cli_entry reload_logger_cli =
- { { "logger", "reload", NULL },
+static struct ast_cli_entry reload_logger_cli =
+ { { "logger", "reload", NULL },
handle_logger_reload, "Reopens the log files",
logger_reload_help };
-static struct ast_cli_entry rotate_logger_cli =
- { { "logger", "rotate", NULL },
+static struct ast_cli_entry rotate_logger_cli =
+ { { "logger", "rotate", NULL },
handle_logger_rotate, "Rotates and reopens the log files",
logger_rotate_help };
-static int handle_SIGXFSZ(int sig)
+static int handle_SIGXFSZ(int sig)
{
/* Indicate need to reload */
filesize_reload_needed = 1;
@@ -614,7 +700,7 @@ int init_logger(void)
ast_cli_register(&logger_show_channels_cli);
mkdir((char *)ast_config_AST_LOG_DIR, 0755);
-
+
/* create log channels */
init_logger_chain();
@@ -661,7 +747,7 @@ void close_logger(void)
return;
}
-static void ast_log_vsyslog(int level, const char *file, int line, const char *function, const char *fmt, va_list args)
+static void ast_log_vsyslog(int level, const char *file, int line, const char *function, const char *fmt, va_list args)
{
char buf[BUFSIZ];
char *s;
@@ -699,12 +785,12 @@ void ast_log(int level, const char *file
char date[256];
va_list ap;
-
+
if (!logchannels)
{
- /*
+ /*
* we don't have the logger chain configured yet,
- * so just log to stdout
+ * so just log to stdout
*/
if (level != __LOG_VERBOSE) {
va_start(ap, fmt);
@@ -728,7 +814,7 @@ void ast_log(int level, const char *file
/* Ignore anything that never gets logged anywhere */
if (!(global_logmask & (1 << level)))
return;
-
+
/* Ignore anything other than the currently debugged file if there is one */
if ((level == __LOG_DEBUG) && !ast_strlen_zero(debug_filename) && strcasecmp(debug_filename, file))
return;
@@ -773,7 +859,7 @@ void ast_log(int level, const char *file
term_color(tmp2, file, COLOR_BRWHITE, 0, sizeof(tmp2)),
term_color(tmp3, linestr, COLOR_BRWHITE, 0, sizeof(tmp3)),
term_color(tmp4, function, COLOR_BRWHITE, 0, sizeof(tmp4)));
-
+
ast_console_puts(buf);
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap);
@@ -793,7 +879,7 @@ void ast_log(int level, const char *file
} else
fprintf(stderr, "Logger Warning: Unable to write to log file '%s': %s (disabled)\n", chan->filename, strerror(errno));
manager_event(EVENT_FLAG_SYSTEM, "LogChannel", "Channel: %s\r\nEnabled: No\r\nReason: %d - %s\r\n", chan->filename, errno, strerror(errno));
- chan->disabled = 1;
+ chan->disabled = 1;
} else {
/* No error message, continue printing */
va_start(ap, fmt);
@@ -827,7 +913,7 @@ void ast_verbose(const char *fmt, ...)
int olen;
struct msglist *m;
struct verb *v;
-
+
va_list ap;
va_start(ap, fmt);
@@ -908,7 +994,7 @@ void ast_verbose(const char *fmt, ...)
if (len) {
if (!complete)
replacelast = 1;
- else
+ else
replacelast = len = 0;
}
@@ -929,7 +1015,7 @@ int ast_verbose_dmesg(void (*v)(const ch
return 0;
}
-int ast_register_verbose(void (*v)(const char *string, int opos, int replacelast, int complete))
+int ast_register_verbose(void (*v)(const char *string, int opos, int replacelast, int complete))
{
struct msglist *m;
struct verb *tmp;
diff -urNp asterisk-1.2.13/Makefile asterisk-queue-log-mysql/Makefile
--- asterisk-1.2.13/Makefile 2006-09-06 14:09:10.000000000 -0600
+++ asterisk-queue-log-mysql/Makefile 2006-12-03 22:10:27.000000000 -0700
@@ -225,7 +225,7 @@ ifeq ($(OSARCH),SunOS)
INSTALL=ginstall
endif
-INCLUDE+=-Iinclude -I../include
+INCLUDE+=-Iinclude -I../include -I/usr/include/mysql
ASTCFLAGS+=-pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE #-DMAKE_VALGRIND_HAPPY
ASTCFLAGS+=$(OPTIMIZE)
ASTOBJ=-o asterisk
@@ -367,7 +367,7 @@ ifeq ($(wildcard $(CROSS_COMPILE_TARGET)
endif
ifeq ($(OSARCH),Linux)
- LIBS+=-ldl -lpthread -lncurses -lm -lresolv #-lnjamd
+ LIBS+=-ldl -lpthread -lncurses -lm -lresolv -L/usr/lib/mysql -lmysqlclient #-lnjamd
else
ifeq ($(OSARCH),SunOS)
LIBS+=-lm -lcurses