diff --git a/main/logger.c b/main/logger.c index 457a6fb53da801b4bbe2733b5e182cf994c62077..332d752c09ad49c43c722c945668c45710958a5e 100644 --- a/main/logger.c +++ b/main/logger.c @@ -1564,12 +1564,24 @@ static struct sigaction handle_SIGXFSZ = { }; /*! \brief Print a normal log message to the channels */ +#define LOG_MSG_PREFIX_LEN 160 static void logger_print_normal(struct logmsg *logmsg) { struct logchannel *chan = NULL; - char buf[BUFSIZ]; + char static_buf[BUFSIZ]; + char *buf = static_buf; + size_t buf_size = sizeof(static_buf); + size_t msg_len = strlen(logmsg->message); int level = 0; + /* Allocate a dynamic buffer if the log message is too long */ + if (msg_len + LOG_MSG_PREFIX_LEN > buf_size) { + buf_size = msg_len + LOG_MSG_PREFIX_LEN; + buf = ast_malloc(buf_size); + if (!buf) + return; + } + AST_RWLIST_RDLOCK(&logchannels); if (!AST_RWLIST_EMPTY(&logchannels)) { AST_RWLIST_TRAVERSE(&logchannels, chan, list) { @@ -1600,13 +1612,38 @@ static void logger_print_normal(struct logmsg *logmsg) /* Don't use LOG_MAKEPRI because it's broken in glibc<2.17 */ syslog_level = chan->facility | syslog_level; /* LOG_MAKEPRI(chan->facility, syslog_level); */ - if (!chan->formatter.format_log(chan, logmsg, buf, BUFSIZ)) { - syslog(syslog_level, "%s", buf); + if (!chan->formatter.format_log(chan, logmsg, buf, buf_size)) { + if (buf == static_buf) { + syslog(syslog_level, "%s", buf); + } else { + /* + * syslog has a the maximum message size limit which is usually 1024 bytes. If a log message + * is longer than this limit, the message could be truncated. In order to show the complete + * messages with longer size, there are two ways to achieve the goal as illustrated below. + * + * 1) Extend the syslog's message size limit + * This is actuall a workaround because no matter how big the limit is, there are always + * chances that a log message is longer than it. In the other hand, long log messages could + * impact the interoperability with some syslog servers when remote syslog is configured. + * 2) Divide an original log message into multiple shorter ones + * This can keep the interoperability with syslog servers and make log message more human + * readable. + */ + char *token, *saveptr; + + /* Long log messages are usually those SIP messages with SDP which are encoded as multiple + * lines */ + for (token = strtok_r(buf, "\r\n", &saveptr); + token; + token = strtok_r(NULL, "\r\n", &saveptr)) { + syslog(syslog_level, "%s", token); + } + } } } break; case LOGTYPE_CONSOLE: - if (!chan->formatter.format_log(chan, logmsg, buf, BUFSIZ)) { + if (!chan->formatter.format_log(chan, logmsg, buf, buf_size)) { ast_console_puts_mutable_full(buf, logmsg->level, logmsg->sublevel); } break; @@ -1618,7 +1655,7 @@ static void logger_print_normal(struct logmsg *logmsg) continue; } - if (chan->formatter.format_log(chan, logmsg, buf, BUFSIZ)) { + if (chan->formatter.format_log(chan, logmsg, buf, buf_size)) { continue; } @@ -1663,6 +1700,9 @@ static void logger_print_normal(struct logmsg *logmsg) ast_verb(1, "Rotated Logs Per SIGXFSZ (Exceeded file size limit)\n"); } + if (buf != static_buf) + ast_free(buf); + return; } @@ -1682,7 +1722,7 @@ static struct logmsg * __attribute__((format(printf, 7, 0))) format_log_message_ } /* Build string */ - res = ast_str_set_va(&buf, BUFSIZ, fmt, ap); + res = ast_str_set_va(&buf, 0, fmt, ap); /* If the build failed, then abort and free this structure */ if (res == AST_DYNSTR_BUILD_FAILED) {