diff options
-rw-r--r-- | CHANGES | 15 | ||||
-rw-r--r-- | cel/cel_odbc.c | 83 | ||||
-rw-r--r-- | configs/samples/hep.conf.sample | 6 | ||||
-rw-r--r-- | configs/samples/logger.conf.sample | 8 | ||||
-rw-r--r-- | include/asterisk/logger.h | 16 | ||||
-rw-r--r-- | main/iostream.c | 67 | ||||
-rw-r--r-- | main/logger.c | 187 | ||||
-rw-r--r-- | main/manager.c | 8 | ||||
-rw-r--r-- | res/res_hep_rtcp.c | 18 | ||||
-rw-r--r-- | tests/test_logger.c | 67 |
10 files changed, 371 insertions, 104 deletions
@@ -31,6 +31,15 @@ res_rtp_asterisk for a response that can never come until we give up on the response. Multiple subnets may be listed. +Logging +------------------- + * Added logger_queue_limit to the configuration options. + All log messages go to a queue serviced by a single thread + which does all the IO. This setting controls how big that + queue can get (and therefore how much memory is allocated) + before new messages are discarded. + The default is 1000. + res_pjsip_config_wizard ------------------ * Two new parameters have been added to the pjsip config wizard. @@ -42,6 +51,12 @@ res_pjsip_config_wizard endpoint/outbound_proxy, aor/outbound_proxy and registration/outbound_proxy parameters. +res_hep_rtcp +------------------ + * If the 'call-id' value is specified for the uuid_type option and a + chan_sip channel is used the resulting HEP traffic will now contain the + SIP Call-ID instead of the Asterisk channel name. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 14.3.0 to Asterisk 14.4.0 ------------ ------------------------------------------------------------------------------ diff --git a/cel/cel_odbc.c b/cel/cel_odbc.c index a0cc6e33a..bdf913cd4 100644 --- a/cel/cel_odbc.c +++ b/cel/cel_odbc.c @@ -35,6 +35,7 @@ #include <sys/types.h> #include <time.h> +#include <math.h> #include <sql.h> #include <sqlext.h> @@ -607,40 +608,62 @@ static void odbc_log(struct ast_event *event) if (ast_strlen_zero(colptr)) { continue; } else { - int year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, fraction = 0; - if (strcasecmp(entry->name, "eventdate") == 0) { - struct ast_tm tm; - ast_localtime(&record.event_time, &tm, tableptr->usegmtime ? "UTC" : NULL); - year = tm.tm_year + 1900; - month = tm.tm_mon + 1; - day = tm.tm_mday; - hour = tm.tm_hour; - minute = tm.tm_min; - second = (tableptr->allowleapsec || tm.tm_sec < 60) ? tm.tm_sec : 59; - fraction = tm.tm_usec; + if (datefield) { + /* + * We've already properly formatted the timestamp so there's no need + * to parse it and re-format it. + */ + ast_str_append(&sql, 0, "%s%s", separator, entry->name); + LENGTHEN_BUF2(27); + ast_str_append(&sql2, 0, "%s{ts '%s'}", separator, colptr); } else { - int count = sscanf(colptr, "%4d-%2d-%2d %2d:%2d:%2d.%6d", &year, &month, &day, &hour, &minute, &second, &fraction); - - if ((count != 3 && count != 5 && count != 6 && count != 7) || year <= 0 || - month <= 0 || month > 12 || day < 0 || day > 31 || - ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) || - (month == 2 && year % 400 == 0 && day > 29) || - (month == 2 && year % 100 == 0 && day > 28) || - (month == 2 && year % 4 == 0 && day > 29) || - (month == 2 && year % 4 != 0 && day > 28) || - hour > 23 || minute > 59 || second > (tableptr->allowleapsec ? 60 : 59) || hour < 0 || minute < 0 || second < 0 || fraction < 0) { - ast_log(LOG_WARNING, "CEL variable %s is not a valid timestamp ('%s').\n", entry->name, colptr); - continue; + int year = 0, month = 0, day = 0, hour = 0, minute = 0; + /* MUST use double for microsecond precision */ + double second = 0.0; + if (strcasecmp(entry->name, "eventdate") == 0) { + /* + * There doesn't seem to be any reference to 'eventdate' anywhere + * other than in this module. It should be considered for removal + * at a later date. + */ + struct ast_tm tm; + ast_localtime(&record.event_time, &tm, tableptr->usegmtime ? "UTC" : NULL); + year = tm.tm_year + 1900; + month = tm.tm_mon + 1; + day = tm.tm_mday; + hour = tm.tm_hour; + minute = tm.tm_min; + second = (tableptr->allowleapsec || tm.tm_sec < 60) ? tm.tm_sec : 59; + second += (tm.tm_usec / 1000000.0); + } else { + /* + * If we're here, the data to be inserted MAY be a timestamp + * but the column is. We parse as much as we can. + */ + int count = sscanf(colptr, "%4d-%2d-%2d %2d:%2d:%lf", &year, &month, &day, &hour, &minute, &second); + + if ((count != 3 && count != 5 && count != 6) || year <= 0 || + month <= 0 || month > 12 || day < 0 || day > 31 || + ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) || + (month == 2 && year % 400 == 0 && day > 29) || + (month == 2 && year % 100 == 0 && day > 28) || + (month == 2 && year % 4 == 0 && day > 29) || + (month == 2 && year % 4 != 0 && day > 28) || + hour > 23 || minute > 59 || ((int)floor(second)) > (tableptr->allowleapsec ? 60 : 59) || + hour < 0 || minute < 0 || ((int)floor(second)) < 0) { + ast_log(LOG_WARNING, "CEL variable %s is not a valid timestamp ('%s').\n", entry->name, colptr); + continue; + } + + if (year > 0 && year < 100) { + year += 2000; + } } - if (year > 0 && year < 100) { - year += 2000; - } + ast_str_append(&sql, 0, "%s%s", separator, entry->name); + LENGTHEN_BUF2(27); + ast_str_append(&sql2, 0, "%s{ts '%04d-%02d-%02d %02d:%02d:%09.6lf'}", separator, year, month, day, hour, minute, second); } - - ast_str_append(&sql, 0, "%s%s", separator, entry->name); - LENGTHEN_BUF2(27); - ast_str_append(&sql2, 0, "%s{ts '%04d-%02d-%02d %02d:%02d:%02d.%d'}", separator, year, month, day, hour, minute, second, fraction); } break; case SQL_INTEGER: diff --git a/configs/samples/hep.conf.sample b/configs/samples/hep.conf.sample index 3d1e74139..32bd8df39 100644 --- a/configs/samples/hep.conf.sample +++ b/configs/samples/hep.conf.sample @@ -24,5 +24,9 @@ capture_id = 1234 ; A unique integer identifier for this ; with each packet from this server. uuid_type = call-id ; Specify the preferred source for the Homer ; correlation UUID. Valid options are: - ; - 'call-id' for the PJSIP SIP Call-ID + ; - 'call-id' for the PJSIP or chan_sip SIP + ; Call-ID ; - 'channel' for the Asterisk channel name + ; Note: If 'call-id' is specified but the + ; channel is not PJSIP or chan_sip then the + ; Asterisk channel name will be used instead. diff --git a/configs/samples/logger.conf.sample b/configs/samples/logger.conf.sample index b504467ec..e5f0c551a 100644 --- a/configs/samples/logger.conf.sample +++ b/configs/samples/logger.conf.sample @@ -78,6 +78,14 @@ ; Directory for log files is configures in asterisk.conf ; option astlogdir ; +; All log messages go to a queue serviced by a single thread +; which does all the IO. This setting controls how big that +; queue can get (and therefore how much memory is allocated) +; before new messages are discarded. +; The default is 1000 +;logger_queue_limit = 250 +; +; [logfiles] ; ; Format is: diff --git a/include/asterisk/logger.h b/include/asterisk/logger.h index 2f629dfbe..849f986b3 100644 --- a/include/asterisk/logger.h +++ b/include/asterisk/logger.h @@ -507,6 +507,22 @@ void ast_verb_console_set(int verb_level); */ int ast_is_logger_initialized(void); +/*! + * \brief Set the maximum number of messages allowed in the processing queue + * + * \param queue_limit + * + * \return Nothing + */ +void ast_logger_set_queue_limit(int queue_limit); + +/*! + * \brief Get the maximum number of messages allowed in the processing queue + * + * \return Queue limit + */ +int ast_logger_get_queue_limit(void); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/main/iostream.c b/main/iostream.c index 6187bc2fb..06414cf43 100644 --- a/main/iostream.c +++ b/main/iostream.c @@ -37,6 +37,39 @@ struct ast_iostream { char rbuf[2048]; }; +#if defined(DO_SSL) +AST_THREADSTORAGE(err2str_threadbuf); +#define ERR2STR_BUFSIZE 128 + +static const char *ssl_error_to_string(int sslerr, int ret) +{ + switch (sslerr) { + case SSL_ERROR_SSL: + return "Internal SSL error"; + case SSL_ERROR_SYSCALL: + if (!ret) { + return "System call EOF"; + } else if (ret == -1) { + char *buf; + + buf = ast_threadstorage_get(&err2str_threadbuf, ERR2STR_BUFSIZE); + if (!buf) { + return "Unknown"; + } + + snprintf(buf, ERR2STR_BUFSIZE, "Underlying BIO error: %s", strerror(errno)); + return buf; + } else { + return "System call other"; + } + default: + break; + } + + return "Unknown"; +} +#endif + int ast_iostream_get_fd(struct ast_iostream *stream) { return stream->fd; @@ -109,13 +142,16 @@ static ssize_t iostream_read(struct ast_iostream *stream, void *buf, size_t size #if defined(DO_SSL) if (stream->ssl) { for (;;) { + int sslerr; + char err[256]; res = SSL_read(stream->ssl, buf, size); if (0 < res) { /* We read some payload data. */ stream->timeout = stream->timeout_reset; return res; } - switch (SSL_get_error(stream->ssl, res)) { + sslerr = SSL_get_error(stream->ssl, res); + switch (sslerr) { case SSL_ERROR_ZERO_RETURN: /* Report EOF for a shutdown */ ast_debug(1, "TLS clean shutdown alert reading data\n"); @@ -163,7 +199,8 @@ static ssize_t iostream_read(struct ast_iostream *stream, void *buf, size_t size break; default: /* Report EOF for an undecoded SSL or transport error. */ - ast_debug(1, "TLS transport or SSL error reading data\n"); + ast_debug(1, "TLS transport or SSL error reading data: %s, %s\n", ERR_error_string(sslerr, err), + ssl_error_to_string(sslerr, res)); return 0; } if (!ms) { @@ -318,6 +355,8 @@ ssize_t ast_iostream_write(struct ast_iostream *stream, const void *buf, size_t written = 0; remaining = size; for (;;) { + int sslerr; + char err[256]; res = SSL_write(stream->ssl, buf + written, remaining); if (res == remaining) { /* Everything was written. */ @@ -329,7 +368,8 @@ ssize_t ast_iostream_write(struct ast_iostream *stream, const void *buf, size_t remaining -= res; continue; } - switch (SSL_get_error(stream->ssl, res)) { + sslerr = SSL_get_error(stream->ssl, res); + switch (sslerr) { case SSL_ERROR_ZERO_RETURN: ast_debug(1, "TLS clean shutdown alert writing data\n"); if (written) { @@ -358,7 +398,8 @@ ssize_t ast_iostream_write(struct ast_iostream *stream, const void *buf, size_t break; default: /* Undecoded SSL or transport error. */ - ast_debug(1, "TLS transport or SSL error writing data\n"); + ast_debug(1, "TLS transport or SSL error writing data: %s, %s\n", ERR_error_string(sslerr, err), + ssl_error_to_string(sslerr, res)); if (written) { /* Report partial write. */ return written; @@ -461,8 +502,10 @@ int ast_iostream_close(struct ast_iostream *stream) */ res = SSL_shutdown(stream->ssl); if (res < 0) { - ast_log(LOG_ERROR, "SSL_shutdown() failed: %d\n", - SSL_get_error(stream->ssl, res)); + int sslerr = SSL_get_error(stream->ssl, res); + char err[256]; + ast_log(LOG_ERROR, "SSL_shutdown() failed: %s, %s\n", + ERR_error_string(sslerr, err), ssl_error_to_string(sslerr, res)); } #if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L @@ -534,7 +577,7 @@ int ast_iostream_start_tls(struct ast_iostream **pstream, SSL_CTX *ssl_ctx, int #ifdef DO_SSL struct ast_iostream *stream = *pstream; int (*ssl_setup)(SSL *) = client ? SSL_connect : SSL_accept; - char err[256]; + int res; stream->ssl = SSL_new(ssl_ctx); if (!stream->ssl) { @@ -551,9 +594,13 @@ int ast_iostream_start_tls(struct ast_iostream **pstream, SSL_CTX *ssl_ctx, int */ SSL_set_fd(stream->ssl, stream->fd); - if (ssl_setup(stream->ssl) <= 0) { - ast_log(LOG_ERROR, "Problem setting up ssl connection: %s\n", - ERR_error_string(ERR_get_error(), err)); + res = ssl_setup(stream->ssl); + if (res <= 0) { + int sslerr = SSL_get_error(stream->ssl, res); + char err[256]; + + ast_log(LOG_ERROR, "Problem setting up ssl connection: %s, %s\n", + ERR_error_string(sslerr, err), ssl_error_to_string(sslerr, res)); errno = EIO; return -1; } diff --git a/main/logger.c b/main/logger.c index 8c8162d71..6060b3c4d 100644 --- a/main/logger.c +++ b/main/logger.c @@ -86,6 +86,11 @@ static int display_callids; AST_THREADSTORAGE(unique_callid); +static int logger_queue_size; +static int logger_queue_limit = 1000; +static int logger_messages_discarded; +static unsigned int high_water_alert; + static enum rotatestrategy { NONE = 0, /* Do not rotate log files at all, instead rely on external mechanisms */ SEQUENTIAL = 1 << 0, /* Original method - create a new file, in order */ @@ -719,6 +724,16 @@ static int init_logger_chain(const char *altconf) fprintf(stderr, "rotatetimestamp option has been deprecated. Please use rotatestrategy instead.\n"); } } + if ((s = ast_variable_retrieve(cfg, "general", "logger_queue_limit"))) { + if (sscanf(s, "%30d", &logger_queue_limit) != 1) { + fprintf(stderr, "logger_queue_limit has an invalid value. Leaving at default of %d.\n", + logger_queue_limit); + } + if (logger_queue_limit < 10) { + fprintf(stderr, "logger_queue_limit must be >= 10. Setting to 10.\n"); + logger_queue_limit = 10; + } + } var = ast_variable_browse(cfg, "logfiles"); for (; var; var = var->next) { @@ -1297,6 +1312,7 @@ static char *handle_logger_show_channels(struct ast_cli_entry *e, int cmd, struc case CLI_GENERATE: return NULL; } + ast_cli(a->fd, "Logger queue limit: %d\n\n", logger_queue_limit); ast_cli(a->fd, FORMATL, "Channel", "Type", "Formatter", "Status"); ast_cli(a->fd, "Configuration\n"); ast_cli(a->fd, FORMATL, "-------", "----", "---------", "------"); @@ -1585,6 +1601,79 @@ static void logger_print_normal(struct logmsg *logmsg) return; } +static struct logmsg * __attribute__((format(printf, 7, 0))) format_log_message_ap(int level, + int sublevel, const char *file, int line, const char *function, ast_callid callid, + const char *fmt, va_list ap) +{ + struct logmsg *logmsg = NULL; + struct ast_str *buf = NULL; + struct ast_tm tm; + struct timeval now = ast_tvnow(); + int res = 0; + char datestring[256]; + + if (!(buf = ast_str_thread_get(&log_buf, LOG_BUF_INIT_SIZE))) { + return NULL; + } + + /* Build string */ + res = ast_str_set_va(&buf, BUFSIZ, fmt, ap); + + /* If the build failed, then abort and free this structure */ + if (res == AST_DYNSTR_BUILD_FAILED) { + return NULL; + } + + /* Create a new logging message */ + if (!(logmsg = ast_calloc_with_stringfields(1, struct logmsg, res + 128))) { + return NULL; + } + + /* Copy string over */ + ast_string_field_set(logmsg, message, ast_str_buffer(buf)); + + /* Set type */ + if (level == __LOG_VERBOSE) { + logmsg->type = LOGMSG_VERBOSE; + } else { + logmsg->type = LOGMSG_NORMAL; + } + + if (display_callids && callid) { + logmsg->callid = callid; + } + + /* Create our date/time */ + ast_localtime(&now, &tm, NULL); + ast_strftime(datestring, sizeof(datestring), dateformat, &tm); + ast_string_field_set(logmsg, date, datestring); + + /* Copy over data */ + logmsg->level = level; + logmsg->sublevel = sublevel; + logmsg->line = line; + ast_string_field_set(logmsg, level_name, levels[level]); + ast_string_field_set(logmsg, file, file); + ast_string_field_set(logmsg, function, function); + logmsg->lwp = ast_get_tid(); + + return logmsg; +} + +static struct logmsg * __attribute__((format(printf, 7, 0))) format_log_message(int level, + int sublevel, const char *file, int line, const char *function, ast_callid callid, + const char *fmt, ...) +{ + struct logmsg *logmsg; + va_list ap; + + va_start(ap, fmt); + logmsg = format_log_message_ap(level, sublevel, file, line, function, callid, fmt, ap); + va_end(ap); + + return logmsg; +} + /*! \brief Actual logging thread */ static void *logger_thread(void *data) { @@ -1601,8 +1690,21 @@ static void *logger_thread(void *data) ast_cond_wait(&logcond, &logmsgs.lock); } } + + if (high_water_alert) { + msg = format_log_message(__LOG_WARNING, 0, "logger", 0, "***", 0, + "Logging resumed. %d message%s discarded.\n", + logger_messages_discarded, logger_messages_discarded == 1 ? "" : "s"); + if (msg) { + AST_LIST_INSERT_TAIL(&logmsgs, msg, list); + } + high_water_alert = 0; + logger_messages_discarded = 0; + } + next = AST_LIST_FIRST(&logmsgs); AST_LIST_HEAD_INIT_NOLOCK(&logmsgs); + logger_queue_size = 0; AST_LIST_UNLOCK(&logmsgs); /* Otherwise go through and process each message in the order added */ @@ -1861,79 +1963,36 @@ void ast_callid_threadstorage_auto_clean(ast_callid callid, int callid_created) /*! * \brief send log messages to syslog and/or the console */ -static void __attribute__((format(printf, 7, 0))) ast_log_full(int level, int sublevel, const char *file, int line, const char *function, ast_callid callid, const char *fmt, va_list ap) +static void __attribute__((format(printf, 7, 0))) ast_log_full(int level, int sublevel, + const char *file, int line, const char *function, ast_callid callid, + const char *fmt, va_list ap) { struct logmsg *logmsg = NULL; - struct ast_str *buf = NULL; - struct ast_tm tm; - struct timeval now = ast_tvnow(); - int res = 0; - char datestring[256]; if (level == __LOG_VERBOSE && ast_opt_remote && ast_opt_exec) { return; } - if (!(buf = ast_str_thread_get(&log_buf, LOG_BUF_INIT_SIZE))) - return; - - if (level != __LOG_VERBOSE && AST_RWLIST_EMPTY(&logchannels)) { - /* - * we don't have the logger chain configured yet, - * so just log to stdout - */ - int result; - result = ast_str_set_va(&buf, BUFSIZ, fmt, ap); /* XXX BUFSIZ ? */ - if (result != AST_DYNSTR_BUILD_FAILED) { - term_filter_escapes(ast_str_buffer(buf)); - fputs(ast_str_buffer(buf), stdout); + AST_LIST_LOCK(&logmsgs); + if (logger_queue_size >= logger_queue_limit && !close_logger_thread) { + logger_messages_discarded++; + if (!high_water_alert && !close_logger_thread) { + logmsg = format_log_message(__LOG_WARNING, 0, "logger", 0, "***", 0, + "Log queue threshold (%d) exceeded. Discarding new messages.\n", logger_queue_limit); + AST_LIST_INSERT_TAIL(&logmsgs, logmsg, list); + high_water_alert = 1; + ast_cond_signal(&logcond); } + AST_LIST_UNLOCK(&logmsgs); return; } + AST_LIST_UNLOCK(&logmsgs); - /* Ignore anything that never gets logged anywhere */ - if (level != __LOG_VERBOSE && !(global_logmask & (1 << level))) - return; - - /* Build string */ - res = ast_str_set_va(&buf, BUFSIZ, fmt, ap); - - /* If the build failed, then abort and free this structure */ - if (res == AST_DYNSTR_BUILD_FAILED) + logmsg = format_log_message_ap(level, sublevel, file, line, function, callid, fmt, ap); + if (!logmsg) { return; - - /* Create a new logging message */ - if (!(logmsg = ast_calloc_with_stringfields(1, struct logmsg, res + 128))) - return; - - /* Copy string over */ - ast_string_field_set(logmsg, message, ast_str_buffer(buf)); - - /* Set type */ - if (level == __LOG_VERBOSE) { - logmsg->type = LOGMSG_VERBOSE; - } else { - logmsg->type = LOGMSG_NORMAL; } - if (display_callids && callid) { - logmsg->callid = callid; - } - - /* Create our date/time */ - ast_localtime(&now, &tm, NULL); - ast_strftime(datestring, sizeof(datestring), dateformat, &tm); - ast_string_field_set(logmsg, date, datestring); - - /* Copy over data */ - logmsg->level = level; - logmsg->sublevel = sublevel; - logmsg->line = line; - ast_string_field_set(logmsg, level_name, levels[level]); - ast_string_field_set(logmsg, file, file); - ast_string_field_set(logmsg, function, function); - logmsg->lwp = ast_get_tid(); - /* If the logger thread is active, append it to the tail end of the list - otherwise skip that step */ if (logthread != AST_PTHREADT_NULL) { AST_LIST_LOCK(&logmsgs); @@ -1942,6 +2001,7 @@ static void __attribute__((format(printf, 7, 0))) ast_log_full(int level, int su logmsg_free(logmsg); } else { AST_LIST_INSERT_TAIL(&logmsgs, logmsg, list); + logger_queue_size++; ast_cond_signal(&logcond); } AST_LIST_UNLOCK(&logmsgs); @@ -2300,3 +2360,12 @@ const char *ast_logger_get_dateformat(void) return dateformat; } +void ast_logger_set_queue_limit(int queue_limit) +{ + logger_queue_limit = queue_limit; +} + +int ast_logger_get_queue_limit(void) +{ + return logger_queue_limit; +} diff --git a/main/manager.c b/main/manager.c index c1d73dce7..c592fbd37 100644 --- a/main/manager.c +++ b/main/manager.c @@ -8736,6 +8736,10 @@ static void manager_shutdown(void) ami_tls_cfg.pvtfile = NULL; ast_free(ami_tls_cfg.cipher); ami_tls_cfg.cipher = NULL; + ast_free(ami_tls_cfg.cafile); + ami_tls_cfg.cafile = NULL; + ast_free(ami_tls_cfg.capath); + ami_tls_cfg.capath = NULL; ao2_global_obj_release(mgr_sessions); @@ -8836,6 +8840,10 @@ static void manager_set_defaults(void) ami_tls_cfg.pvtfile = ast_strdup(""); ast_free(ami_tls_cfg.cipher); ami_tls_cfg.cipher = ast_strdup(""); + ast_free(ami_tls_cfg.cafile); + ami_tls_cfg.cafile = ast_strdup(""); + ast_free(ami_tls_cfg.capath); + ami_tls_cfg.capath = ast_strdup(""); } static int __init_manager(int reload, int by_external_config) diff --git a/res/res_hep_rtcp.c b/res/res_hep_rtcp.c index 7191f4661..395031a3d 100644 --- a/res/res_hep_rtcp.c +++ b/res/res_hep_rtcp.c @@ -53,12 +53,22 @@ static char *assign_uuid(struct ast_json *json_channel) return NULL; } - if (uuid_type == HEP_UUID_TYPE_CALL_ID && ast_begins_with(channel_name, "PJSIP")) { - struct ast_channel *chan = ast_channel_get_by_name(channel_name); + if (uuid_type == HEP_UUID_TYPE_CALL_ID) { + struct ast_channel *chan = NULL; char buf[128]; - if (chan && !ast_func_read(chan, "CHANNEL(pjsip,call-id)", buf, sizeof(buf))) { - uuid = ast_strdup(buf); + if (ast_begins_with(channel_name, "PJSIP")) { + chan = ast_channel_get_by_name(channel_name); + + if (chan && !ast_func_read(chan, "CHANNEL(pjsip,call-id)", buf, sizeof(buf))) { + uuid = ast_strdup(buf); + } + } else if (ast_begins_with(channel_name, "SIP")) { + chan = ast_channel_get_by_name(channel_name); + + if (chan && !ast_func_read(chan, "SIP_HEADER(call-id)", buf, sizeof(buf))) { + uuid = ast_strdup(buf); + } } ast_channel_cleanup(chan); diff --git a/tests/test_logger.c b/tests/test_logger.c index 07a4c369b..59ee3e6c1 100644 --- a/tests/test_logger.c +++ b/tests/test_logger.c @@ -188,9 +188,76 @@ static char *handle_cli_performance_test(struct ast_cli_entry *e, int cmd, struc return CLI_SUCCESS; } +static char *handle_cli_queue_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + unsigned int level; + int current_queue_limit; + unsigned int x; + struct timeval start, end; + int elapsed; + char tmppath[] = "/tmp/asterisk_logger_queue.XXXXXX"; + int fd; + + switch (cmd) { + case CLI_INIT: + e->command = "logger test queue"; + e->usage = "" + "Usage: logger test queue\n" + ""; + return NULL; + case CLI_GENERATE: + return NULL; + } + + fd = mkstemp(tmppath); + if (fd < 0) { + ast_cli(a->fd, "Test: Failed, could not create temporary log file '%s'.\n", tmppath); + return CLI_SUCCESS; + } + + level = ast_logger_register_level("queuetest"); + if (level < 0) { + ast_cli(a->fd, "Test: Failed, could not register level 'queuetest'.\n"); + return CLI_SUCCESS; + } + ast_cli(a->fd, "Test: got level %u for 'queuetest'.\n", level); + + if (ast_logger_create_channel(tmppath, "queuetest") != AST_LOGGER_SUCCESS) { + ast_cli(a->fd, "Test: Unable to create logger channel '%s'\n", tmppath); + goto error; + } + + current_queue_limit = ast_logger_get_queue_limit(); + ast_cli(a->fd, "Test: Current queue limit: %d. Setting to 100 for test.\n", current_queue_limit); + ast_logger_set_queue_limit(100); + + ast_cli(a->fd, "Test: You should see SOME 'exceeded' and 'resumed' messages after the test " + "is completed. How many is dependent on system resources.\n"); + + start = ast_tvnow(); + for (x = 0; x < 10000; x++) { + ast_log_dynamic_level(level, "Performance test log message %2d\n", x); + } + end = ast_tvnow(); + elapsed = ast_tvdiff_ms(end, start); + ast_cli(a->fd, "Test: 10,000 messages in %f seconds.\n", (float) elapsed / 1000); + ast_cli(a->fd, "Test: Completed. Resetting queue limit to %d.\n", current_queue_limit); + ast_logger_set_queue_limit(current_queue_limit); + +error: + + ast_logger_remove_channel(tmppath); + ast_logger_unregister_level("queuetest"); + close(fd); + unlink(tmppath); + + return CLI_SUCCESS; +} + static struct ast_cli_entry cli_logger[] = { AST_CLI_DEFINE(handle_cli_dynamic_level_test, "Test the dynamic logger level implementation"), AST_CLI_DEFINE(handle_cli_performance_test, "Test the logger performance"), + AST_CLI_DEFINE(handle_cli_queue_test, "Test the logger queue"), }; static int unload_module(void) |