<p>Kevin Harwell <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/16508">View Change</a></p><div style="white-space:pre-wrap">Approvals:
George Joseph: Looks good to me, approved
Kevin Harwell: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">logger: Add custom logging capabilities<br><br>Adds the ability for users to log to custom log levels<br>by providing custom log level names in logger.conf. Also<br>adds a logger show levels CLI command.<br><br>ASTERISK-29529<br><br>Change-Id: If082703cf81a436ae5a565c75225fa8c0554b702<br>---<br>M apps/app_verbose.c<br>M configs/samples/logger.conf.sample<br>A doc/CHANGES-staging/logger.txt<br>M include/asterisk/logger.h<br>M main/logger.c<br>5 files changed, 183 insertions(+), 34 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_verbose.c b/apps/app_verbose.c</span><br><span>index 5b78e18..a888ba0 100644</span><br><span>--- a/apps/app_verbose.c</span><br><span>+++ b/apps/app_verbose.c</span><br><span>@@ -33,6 +33,7 @@</span><br><span> #include "asterisk/module.h"</span><br><span> #include "asterisk/app.h"</span><br><span> #include "asterisk/channel.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/logger.h"</span><br><span> </span><br><span> static char *app_verbose = "Verbose";</span><br><span> static char *app_log = "Log";</span><br><span>@@ -61,7 +62,8 @@</span><br><span> <syntax></span><br><span> <parameter name="level" required="true"></span><br><span> <para>Level must be one of <literal>ERROR</literal>, <literal>WARNING</literal>, <literal>NOTICE</literal>,</span><br><span style="color: hsl(0, 100%, 40%);">- <literal>DEBUG</literal>, <literal>VERBOSE</literal> or <literal>DTMF</literal>.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <literal>DEBUG</literal>, <literal>VERBOSE</literal>, <literal>DTMF</literal>, or</span><br><span style="color: hsl(120, 100%, 40%);">+ the name of a custom dynamic logging level.</para></span><br><span> </parameter></span><br><span> <parameter name="message" required="true"></span><br><span> <para>Output text message.</para></span><br><span>@@ -135,7 +137,7 @@</span><br><span> } else if (!strcasecmp(args.level, "DTMF")) {</span><br><span> lnum = __LOG_DTMF;</span><br><span> } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_ERROR, "Unknown log level: '%s'\n", args.level);</span><br><span style="color: hsl(120, 100%, 40%);">+ lnum = ast_logger_get_dynamic_level(args.level);</span><br><span> }</span><br><span> </span><br><span> if (lnum > -1) {</span><br><span>@@ -143,6 +145,9 @@</span><br><span> snprintf(extension, sizeof(extension), "Ext. %s", ast_channel_exten(chan));</span><br><span> </span><br><span> ast_log(lnum, extension, ast_channel_priority(chan), context, "%s\n", args.msg);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Unknown log level: '%s'\n", args.level);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span> }</span><br><span> </span><br><span> return 0;</span><br><span>diff --git a/configs/samples/logger.conf.sample b/configs/samples/logger.conf.sample</span><br><span>index 9e2fb35..777f803 100644</span><br><span>--- a/configs/samples/logger.conf.sample</span><br><span>+++ b/configs/samples/logger.conf.sample</span><br><span>@@ -85,6 +85,11 @@</span><br><span> ; The default is 1000</span><br><span> ;logger_queue_limit = 250</span><br><span> ;</span><br><span style="color: hsl(120, 100%, 40%);">+; Any custom logging levels you may want to use, which can then</span><br><span style="color: hsl(120, 100%, 40%);">+; be sent to logging channels. The maximum number of custom</span><br><span style="color: hsl(120, 100%, 40%);">+; levels is 16, but not all of these may be available if modules</span><br><span style="color: hsl(120, 100%, 40%);">+; in Asterisk define their own.</span><br><span style="color: hsl(120, 100%, 40%);">+;custom_levels = foobar,important,compliance</span><br><span> ;</span><br><span> [logfiles]</span><br><span> ;</span><br><span>@@ -130,6 +135,7 @@</span><br><span> ; dtmf</span><br><span> ; fax</span><br><span> ; security</span><br><span style="color: hsl(120, 100%, 40%);">+; <customlevel></span><br><span> ;</span><br><span> ; Verbose takes an optional argument, in the form of an integer level. The</span><br><span> ; verbose level can be set per logfile. Verbose messages with higher levels</span><br><span>@@ -176,3 +182,5 @@</span><br><span> ;</span><br><span> ;syslog.local0 => notice,warning,error</span><br><span> ;</span><br><span style="color: hsl(120, 100%, 40%);">+; A log level defined in 'custom_levels' above</span><br><span style="color: hsl(120, 100%, 40%);">+;important.log = important</span><br><span>diff --git a/doc/CHANGES-staging/logger.txt b/doc/CHANGES-staging/logger.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..d09ebcc</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/logger.txt</span><br><span>@@ -0,0 +1,5 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: logger</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Added the ability to define custom log levels in logger.conf</span><br><span style="color: hsl(120, 100%, 40%);">+and use them in the Log dialplan application. Also adds a</span><br><span style="color: hsl(120, 100%, 40%);">+logger show levels CLI command.</span><br><span>diff --git a/include/asterisk/logger.h b/include/asterisk/logger.h</span><br><span>index d823ed4..4234262 100644</span><br><span>--- a/include/asterisk/logger.h</span><br><span>+++ b/include/asterisk/logger.h</span><br><span>@@ -330,6 +330,14 @@</span><br><span> int ast_logger_register_level(const char *name);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Retrieve dynamic logging level id</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param name The name of the level</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval The unique integer id for the given level</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 if level name not found</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_logger_get_dynamic_level(const char *name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Unregister a previously registered logger level</span><br><span> * \param name The name of the level to be unregistered</span><br><span> * \return nothing</span><br><span>diff --git a/main/logger.c b/main/logger.c</span><br><span>index 457a6fb..6b0e76f 100644</span><br><span>--- a/main/logger.c</span><br><span>+++ b/main/logger.c</span><br><span>@@ -74,6 +74,10 @@</span><br><span> /*** DOCUMENTATION</span><br><span> ***/</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int logger_register_level(const char *name);</span><br><span style="color: hsl(120, 100%, 40%);">+static int logger_unregister_level(const char *name);</span><br><span style="color: hsl(120, 100%, 40%);">+static int logger_get_dynamic_level(const char *name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static char dateformat[256] = "%b %e %T"; /* Original Asterisk Format */</span><br><span> </span><br><span> static char queue_log_name[256] = QUEUELOG;</span><br><span>@@ -211,6 +215,15 @@</span><br><span> "DTMF",</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Custom dynamic logging levels added by the user</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The first 16 levels are reserved for system usage, and the remaining</span><br><span style="color: hsl(120, 100%, 40%);">+ * levels are reserved for usage by dynamic levels registered via</span><br><span style="color: hsl(120, 100%, 40%);">+ * ast_logger_register_level.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static char *custom_dynamic_levels[NUMLOGLEVELS];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief Colors used in the console for logging */</span><br><span> static const int colors[NUMLOGLEVELS] = {</span><br><span> COLOR_BRGREEN,</span><br><span>@@ -697,6 +710,26 @@</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Checks if level exists in array of level names</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param levels Array of level names</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param level Name to search for</span><br><span style="color: hsl(120, 100%, 40%);">+ * \len Size of levels</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 1 Found</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 Not Found</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int custom_level_still_exists(char **levels, char *level, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < len; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcmp(levels[i], level)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span> * \brief Read config, setup channels.</span><br><span> * \param altconf Alternate configuration file to read.</span><br><span> *</span><br><span>@@ -809,6 +842,39 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Custom dynamic logging levels defined by user */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((s = ast_variable_retrieve(cfg, "general", "custom_levels"))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ char *customlogs = ast_strdupa(s);</span><br><span style="color: hsl(120, 100%, 40%);">+ char *logfile;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *new_custom_levels[16] = { };</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int level, new_level = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* get the custom levels we need to register or reload */</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((logfile = strsep(&customlogs, ","))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ new_custom_levels[new_level++] = logfile;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* unregister existing custom levels, if they're not still</span><br><span style="color: hsl(120, 100%, 40%);">+ specified in customlogs, to make room for new levels */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (level = 16; level < ARRAY_LEN(levels); level++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (levels[level] && custom_dynamic_levels[level] &&</span><br><span style="color: hsl(120, 100%, 40%);">+ !custom_level_still_exists(new_custom_levels, levels[level], ARRAY_LEN(new_custom_levels))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ logger_unregister_level(levels[level]);</span><br><span style="color: hsl(120, 100%, 40%);">+ custom_dynamic_levels[level] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ new_level = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((logfile = new_custom_levels[new_level++])) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Lock already held, so directly register the level,</span><br><span style="color: hsl(120, 100%, 40%);">+ unless it's already registered (as during reload) */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (logger_get_dynamic_level(logfile) == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ int custom_level = logger_register_level(logfile);</span><br><span style="color: hsl(120, 100%, 40%);">+ custom_dynamic_levels[custom_level] = logfile;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> var = ast_variable_browse(cfg, "logfiles");</span><br><span> for (; var; var = var->next) {</span><br><span> chan = make_logchannel(var->name, var->value, var->lineno, 0);</span><br><span>@@ -1403,6 +1469,35 @@</span><br><span> return CLI_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief CLI command to show logging levels */</span><br><span style="color: hsl(120, 100%, 40%);">+static char *handle_logger_show_levels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+#define FORMATL2 "%5s %s\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int level;</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ e->command = "logger show levels";</span><br><span style="color: hsl(120, 100%, 40%);">+ e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+ "Usage: logger show levels\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " List configured logger levels.\n";</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_GENERATE:</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, FORMATL2, "Level", "Name");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, FORMATL2, "-----", "----");</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_RWLIST_RDLOCK(&logchannels);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (level = 0; level < ARRAY_LEN(levels); level++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (levels[level]) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "%5d %s\n", level, levels[level]);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_RWLIST_UNLOCK(&logchannels);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int ast_logger_create_channel(const char *log_channel, const char *components)</span><br><span> {</span><br><span> struct logchannel *chan;</span><br><span>@@ -1545,6 +1640,7 @@</span><br><span> </span><br><span> static struct ast_cli_entry cli_logger[] = {</span><br><span> AST_CLI_DEFINE(handle_logger_show_channels, "List configured log channels"),</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_CLI_DEFINE(handle_logger_show_levels, "List configured log levels"),</span><br><span> AST_CLI_DEFINE(handle_logger_reload, "Reopens the log files"),</span><br><span> AST_CLI_DEFINE(handle_logger_rotate, "Rotates and reopens the log files"),</span><br><span> AST_CLI_DEFINE(handle_logger_set_level, "Enables/Disables a specific logging level for this console"),</span><br><span>@@ -2348,19 +2444,14 @@</span><br><span> {</span><br><span> struct logchannel *cur;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- AST_RWLIST_WRLOCK(&logchannels);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> global_logmask = 0;</span><br><span> </span><br><span> AST_RWLIST_TRAVERSE(&logchannels, cur, list) {</span><br><span> make_components(cur);</span><br><span> global_logmask |= cur->logmask;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- AST_RWLIST_UNLOCK(&logchannels);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> #ifdef AST_DEVMODE</span><br><span> </span><br><span> AST_THREADSTORAGE_RAW(trace_indent);</span><br><span>@@ -2452,13 +2543,12 @@</span><br><span> }</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int ast_logger_register_level(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+/* Lock should be held before calling this function */</span><br><span style="color: hsl(120, 100%, 40%);">+static int logger_register_level(const char *name)</span><br><span> {</span><br><span> unsigned int level;</span><br><span> unsigned int available = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- AST_RWLIST_WRLOCK(&logchannels);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> for (level = 0; level < ARRAY_LEN(levels); level++) {</span><br><span> if ((level >= 16) && !available && !levels[level]) {</span><br><span> available = level;</span><br><span>@@ -2469,7 +2559,6 @@</span><br><span> ast_log(LOG_WARNING,</span><br><span> "Unable to register dynamic logger level '%s': a standard logger level uses that name.\n",</span><br><span> name);</span><br><span style="color: hsl(0, 100%, 40%);">- AST_RWLIST_UNLOCK(&logchannels);</span><br><span> </span><br><span> return -1;</span><br><span> }</span><br><span>@@ -2479,15 +2568,12 @@</span><br><span> ast_log(LOG_WARNING,</span><br><span> "Unable to register dynamic logger level '%s'; maximum number of levels registered.\n",</span><br><span> name);</span><br><span style="color: hsl(0, 100%, 40%);">- AST_RWLIST_UNLOCK(&logchannels);</span><br><span> </span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span> levels[available] = ast_strdup(name);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- AST_RWLIST_UNLOCK(&logchannels);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> ast_debug(1, "Registered dynamic logger level '%s' with index %u.\n", name, available);</span><br><span> </span><br><span> update_logchannels();</span><br><span>@@ -2495,42 +2581,79 @@</span><br><span> return available;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-void ast_logger_unregister_level(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_logger_register_level(const char *name)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int found = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int x;</span><br><span style="color: hsl(120, 100%, 40%);">+ int available = 0;</span><br><span> </span><br><span> AST_RWLIST_WRLOCK(&logchannels);</span><br><span style="color: hsl(120, 100%, 40%);">+ available = logger_register_level(name);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_RWLIST_UNLOCK(&logchannels);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return available;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int logger_get_dynamic_level(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int level = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int x;</span><br><span> </span><br><span> for (x = 16; x < ARRAY_LEN(levels); x++) {</span><br><span> if (!levels[x]) {</span><br><span> continue;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (strcasecmp(levels[x], name)) {</span><br><span style="color: hsl(0, 100%, 40%);">- continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcasecmp(levels[x], name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ level = x;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- found = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (found) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* take this level out of the global_logmask, to ensure that no new log messages</span><br><span style="color: hsl(0, 100%, 40%);">- * will be queued for it</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(120, 100%, 40%);">+ return level;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- global_logmask &= ~(1 << x);</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_logger_get_dynamic_level(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int level = -1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(levels[x]);</span><br><span style="color: hsl(0, 100%, 40%);">- levels[x] = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- AST_RWLIST_UNLOCK(&logchannels);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_RWLIST_RDLOCK(&logchannels);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(1, "Unregistered dynamic logger level '%s' with index %u.\n", name, x);</span><br><span style="color: hsl(120, 100%, 40%);">+ level = logger_get_dynamic_level(name);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ AST_RWLIST_UNLOCK(&logchannels);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return level;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int logger_unregister_level(const char *name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int x;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ x = logger_get_dynamic_level(name);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (x == -1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* take this level out of the global_logmask, to ensure that no new log messages</span><br><span style="color: hsl(120, 100%, 40%);">+ * will be queued for it</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ global_logmask &= ~(1 << x);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(levels[x]);</span><br><span style="color: hsl(120, 100%, 40%);">+ levels[x] = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ return x;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_logger_unregister_level(const char *name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int x;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_RWLIST_WRLOCK(&logchannels);</span><br><span style="color: hsl(120, 100%, 40%);">+ x = logger_unregister_level(name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (x) {</span><br><span> update_logchannels();</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- AST_RWLIST_UNLOCK(&logchannels);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_RWLIST_UNLOCK(&logchannels);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (x) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(1, "Unregistered dynamic logger level '%s' with index %u.\n", name, x);</span><br><span> }</span><br><span> }</span><br><span> </span><br><span></span><br></pre><div style="white-space:pre-wrap"></div><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/16508">change 16508</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/16508"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: If082703cf81a436ae5a565c75225fa8c0554b702 </div>
<div style="display:none"> Gerrit-Change-Number: 16508 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: N A <mail@interlinked.x10host.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>