Make logger respond better to lack of disk space and add "logger show channels" CLI (bug #3909 with minor mods)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5321 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2-netsec
Mark Spencer 20 years ago
parent b6fd23d966
commit 642059b2e4

@ -23,6 +23,7 @@
#include <asterisk/term.h> #include <asterisk/term.h>
#include <asterisk/cli.h> #include <asterisk/cli.h>
#include <asterisk/utils.h> #include <asterisk/utils.h>
#include <asterisk/manager.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
@ -56,6 +57,7 @@ static int syslog_level_map[] = {
#endif #endif
static char dateformat[256] = "%b %e %T"; /* Original Asterisk Format */ static char dateformat[256] = "%b %e %T"; /* Original Asterisk Format */
AST_MUTEX_DEFINE_STATIC(msglist_lock); AST_MUTEX_DEFINE_STATIC(msglist_lock);
AST_MUTEX_DEFINE_STATIC(loglock); AST_MUTEX_DEFINE_STATIC(loglock);
static int pending_logger_reload = 0; static int pending_logger_reload = 0;
@ -73,14 +75,20 @@ static struct msglist {
static char hostname[256]; static char hostname[256];
enum logtypes {
LOGTYPE_SYSLOG,
LOGTYPE_FILE,
LOGTYPE_CONSOLE,
};
struct logchannel { struct logchannel {
int logmask; int logmask; /* What to log to this channel */
int facility; /* syslog */ int disabled; /* If this channel is disabled or not */
int syslog; /* syslog flag */ int facility; /* syslog facility */
int console; /* console logging */ enum logtypes type; /* Type of log channel */
FILE *fileptr; /* logfile logging */ FILE *fileptr; /* logfile logging file pointer */
char filename[256]; char filename[256]; /* Filename */
struct logchannel *next; struct logchannel *next; /* Next channel in chain */
}; };
static struct logchannel *logchannels = NULL; static struct logchannel *logchannels = NULL;
@ -152,7 +160,7 @@ static struct logchannel *make_logchannel(char *channel, char *components, int l
if (chan) { if (chan) {
memset(chan, 0, sizeof(struct logchannel)); memset(chan, 0, sizeof(struct logchannel));
if (!strcasecmp(channel, "console")) { if (!strcasecmp(channel, "console")) {
chan->console = 1; chan->type = LOGTYPE_CONSOLE;
} else if (!strncasecmp(channel, "syslog", 6)) { } else if (!strncasecmp(channel, "syslog", 6)) {
/* /*
* syntax is: * syntax is:
@ -215,7 +223,7 @@ static struct logchannel *make_logchannel(char *channel, char *components, int l
chan->facility = LOG_LOCAL6; chan->facility = LOG_LOCAL6;
else if (!strcasecmp(facility, "LOCAL7")) else if (!strcasecmp(facility, "LOCAL7"))
chan->facility = LOG_LOCAL7; chan->facility = LOG_LOCAL7;
#endif #endif /* Solaris */
if (0 > chan->facility) { if (0 > chan->facility) {
fprintf(stderr, "Logger Warning: bad syslog facility in logger.conf\n"); fprintf(stderr, "Logger Warning: bad syslog facility in logger.conf\n");
@ -223,7 +231,7 @@ static struct logchannel *make_logchannel(char *channel, char *components, int l
return NULL; return NULL;
} }
chan->syslog = 1; chan->type = LOGTYPE_SYSLOG;
openlog("asterisk", LOG_PID, chan->facility); openlog("asterisk", LOG_PID, chan->facility);
} else { } else {
if (channel[0] == '/') { if (channel[0] == '/') {
@ -244,6 +252,7 @@ static struct logchannel *make_logchannel(char *channel, char *components, int l
/* Can't log here, since we're called with a lock */ /* 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)); 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); chan->logmask = make_components(components, lineno);
} }
@ -337,6 +346,7 @@ static void queue_log_init(void)
{ {
char filename[256]; char filename[256];
int reloaded = 0; int reloaded = 0;
ast_mutex_lock(&qloglock); ast_mutex_lock(&qloglock);
if (qlog) { if (qlog) {
reloaded = 1; reloaded = 1;
@ -360,8 +370,8 @@ int reload_logger(int rotate)
char new[AST_CONFIG_MAX_PATH]; char new[AST_CONFIG_MAX_PATH];
struct logchannel *f; struct logchannel *f;
FILE *myf; FILE *myf;
int x; int x;
ast_mutex_lock(&loglock); ast_mutex_lock(&loglock);
if (eventlog) if (eventlog)
fclose(eventlog); fclose(eventlog);
@ -369,8 +379,6 @@ int reload_logger(int rotate)
rotate = 0; rotate = 0;
eventlog = NULL; eventlog = NULL;
mkdir((char *)ast_config_AST_LOG_DIR, 0755); mkdir((char *)ast_config_AST_LOG_DIR, 0755);
snprintf(old, sizeof(old), "%s/%s", (char *)ast_config_AST_LOG_DIR, EVENTLOG); snprintf(old, sizeof(old), "%s/%s", (char *)ast_config_AST_LOG_DIR, EVENTLOG);
@ -379,7 +387,7 @@ int reload_logger(int rotate)
for (x=0;;x++) { for (x=0;;x++) {
snprintf(new, sizeof(new), "%s/%s.%d", (char *)ast_config_AST_LOG_DIR, EVENTLOG,x); snprintf(new, sizeof(new), "%s/%s.%d", (char *)ast_config_AST_LOG_DIR, EVENTLOG,x);
myf = fopen((char *)new, "r"); myf = fopen((char *)new, "r");
if (myf) if (myf) /* File exists */
fclose(myf); fclose(myf);
else else
break; break;
@ -395,8 +403,12 @@ int reload_logger(int rotate)
f = logchannels; f = logchannels;
while(f) { while(f) {
if (f->disabled) {
f->disabled = 0; /* Re-enable logging at reload */
manager_event(EVENT_FLAG_SYSTEM, "LogChannel", "Channel: %s\r\nEnabled: Yes\r\n", f->filename);
}
if (f->fileptr && (f->fileptr != stdout) && (f->fileptr != stderr)) { if (f->fileptr && (f->fileptr != stdout) && (f->fileptr != stderr)) {
fclose(f->fileptr); fclose(f->fileptr); /* Close file */
f->fileptr = NULL; f->fileptr = NULL;
if(rotate) { if(rotate) {
strncpy(old, f->filename, sizeof(old) - 1); strncpy(old, f->filename, sizeof(old) - 1);
@ -439,23 +451,59 @@ int reload_logger(int rotate)
static int handle_logger_reload(int fd, int argc, char *argv[]) static int handle_logger_reload(int fd, int argc, char *argv[])
{ {
if(reload_logger(0)) if(reload_logger(0)) {
{
ast_cli(fd, "Failed to reload the logger\n"); ast_cli(fd, "Failed to reload the logger\n");
return RESULT_FAILURE; return RESULT_FAILURE;
} } else
else
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
static int handle_logger_rotate(int fd, int argc, char *argv[]) static int handle_logger_rotate(int fd, int argc, char *argv[])
{ {
if(reload_logger(1)) if(reload_logger(1)) {
{
ast_cli(fd, "Failed to reload the logger and rotate log files\n"); ast_cli(fd, "Failed to reload the logger and rotate log files\n");
return RESULT_FAILURE; return RESULT_FAILURE;
} else
return RESULT_SUCCESS;
}
/*--- handle_logger_show_channels: CLI command to show logging system
configuration */
static int handle_logger_show_channels(int fd, int argc, char *argv[])
{
#define FORMATL "%-35.35s %-8.8s %-9.9s "
struct logchannel *chan;
ast_mutex_lock(&loglock);
chan = logchannels;
ast_cli(fd,FORMATL, "Channel", "Type", "Status");
ast_cli(fd, "Configuration\n");
ast_cli(fd,FORMATL, "-------", "----", "------");
ast_cli(fd, "-------------\n");
while (chan) {
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))
ast_cli(fd, "Debug ");
if (chan->logmask & (1 << __LOG_VERBOSE))
ast_cli(fd, "Verbose ");
if (chan->logmask & (1 << __LOG_WARNING))
ast_cli(fd, "Warning ");
if (chan->logmask & (1 << __LOG_NOTICE))
ast_cli(fd, "Notice ");
if (chan->logmask & (1 << __LOG_ERROR))
ast_cli(fd, "Error ");
if (chan->logmask & (1 << __LOG_EVENT))
ast_cli(fd, "Event ");
ast_cli(fd, "\n");
chan = chan->next;
} }
else ast_cli(fd, "\n");
ast_mutex_unlock(&loglock);
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
@ -467,12 +515,21 @@ static struct verb {
static char logger_reload_help[] = static char logger_reload_help[] =
"Usage: logger reload\n" "Usage: logger reload\n"
" Reloads the logger subsystem state. Use after restarting syslogd(8)\n"; " Reloads the logger subsystem state. Use after restarting syslogd(8) if you are using syslog logging.\n";
static char logger_rotate_help[] = static char logger_rotate_help[] =
"Usage: logger rotate\n" "Usage: logger rotate\n"
" Rotates and Reopens the log files.\n"; " Rotates and Reopens the log files.\n";
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 },
handle_logger_show_channels, "List configured log channels",
logger_show_channels_help };
static struct ast_cli_entry reload_logger_cli = static struct ast_cli_entry reload_logger_cli =
{ { "logger", "reload", NULL }, { { "logger", "reload", NULL },
handle_logger_reload, "Reopens the log files", handle_logger_reload, "Reopens the log files",
@ -500,6 +557,7 @@ int init_logger(void)
/* register the relaod logger cli command */ /* register the relaod logger cli command */
ast_cli_register(&reload_logger_cli); ast_cli_register(&reload_logger_cli);
ast_cli_register(&rotate_logger_cli); ast_cli_register(&rotate_logger_cli);
ast_cli_register(&logger_show_channels_cli);
/* initialize queue logger */ /* initialize queue logger */
queue_log_init(); queue_log_init();
@ -609,12 +667,14 @@ void ast_log(int level, const char *file, int line, const char *function, const
if (logchannels) { if (logchannels) {
chan = logchannels; chan = logchannels;
while(chan) { while(chan && !chan->disabled) {
if (chan->syslog && (chan->logmask & (1 << level))) { /* Check syslog channels */
if (chan->type == LOG_SYSLOG && (chan->logmask & (1 << level))) {
va_start(ap, fmt); va_start(ap, fmt);
ast_log_vsyslog(level, file, line, function, fmt, ap); ast_log_vsyslog(level, file, line, function, fmt, ap);
va_end(ap); va_end(ap);
} else if ((chan->logmask & (1 << level)) && (chan->console)) { /* Console channels */
} else if ((chan->logmask & (1 << level)) && (chan->type == LOGTYPE_CONSOLE)) {
char linestr[128]; char linestr[128];
char tmp1[80], tmp2[80], tmp3[80], tmp4[80]; char tmp1[80], tmp2[80], tmp3[80], tmp4[80];
@ -634,16 +694,29 @@ void ast_log(int level, const char *file, int line, const char *function, const
va_end(ap); va_end(ap);
ast_console_puts(buf); ast_console_puts(buf);
} }
/* File channels */
} else if ((chan->logmask & (1 << level)) && (chan->fileptr)) { } else if ((chan->logmask & (1 << level)) && (chan->fileptr)) {
snprintf(buf, sizeof(buf), option_timestamp ? "[%s] %s[%ld]: " : "%s %s[%ld]: ", date, int res;
levels[level], (long)GETTID()); snprintf(buf, sizeof(buf), option_timestamp ? "[%s] %s[%ld]: " : "%s %s[%ld] %s: ", date,
fprintf(chan->fileptr, buf); levels[level], (long)GETTID(), file);
res = fprintf(chan->fileptr, buf);
if (res <= 0 && buf[0] != '\0') { /* Error, no characters printed */
fprintf(stderr,"**** Asterisk Logging Error: ***********\n");
if (errno == ENOMEM || errno == ENOSPC) {
fprintf(stderr, "Asterisk logging error: Out of disk space, can't log to log file %s\n", chan->filename);
} 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;
} else {
/* No error message, continue printing */
va_start(ap, fmt); va_start(ap, fmt);
vsnprintf(buf, sizeof(buf), fmt, ap); vsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap); va_end(ap);
fputs(buf, chan->fileptr); fputs(buf, chan->fileptr);
fflush(chan->fileptr); fflush(chan->fileptr);
} }
}
chan = chan->next; chan = chan->next;
} }
} else { } else {
@ -663,9 +736,9 @@ void ast_log(int level, const char *file, int line, const char *function, const
/* end critical section */ /* end critical section */
if (pending_logger_reload) { if (pending_logger_reload) {
reload_logger(1); reload_logger(1);
ast_log(LOG_EVENT,"Rotated Logs Per SIGXFSZ\n"); ast_log(LOG_EVENT,"Rotated Logs Per SIGXFSZ (Exceeded file size limit)\n");
if (option_verbose) if (option_verbose)
ast_verbose("Rotated Logs Per SIGXFSZ\n"); ast_verbose("Rotated Logs Per SIGXFSZ (Exceeded file size limit)\n");
} }
} }

Loading…
Cancel
Save