55 #include "asterisk/logger_category.h"
69 #include "asterisk/buildinfo.h"
77 static int logger_register_level(
const char *name);
78 static int logger_unregister_level(
const char *name);
79 static int logger_get_dynamic_level(
const char *name);
81 static char dateformat[256] =
"%b %e %T";
83 static char queue_log_name[256] = QUEUELOG;
84 static char exec_after_rotate[256] =
"";
86 static int filesize_reload_needed;
87 static unsigned int global_logmask = 0xFFFF;
88 static int queuelog_init;
89 static int logger_initialized;
90 static volatile int next_unique_callid = 1;
91 static int display_callids;
95 static int logger_queue_size;
96 static int logger_queue_limit = 1000;
97 static int logger_messages_discarded;
98 static unsigned int high_water_alert;
103 #define LOGMSG_SIZE MAX(BUFSIZ, 8192)
105 static enum rotatestrategy {
110 } rotatestrategy = SEQUENTIAL;
113 unsigned int queue_log:1;
114 unsigned int queue_log_to_file:1;
115 unsigned int queue_adaptive_realtime:1;
116 unsigned int queue_log_realtime_use_gmt:1;
119 static char hostname[MAXHOSTNAMELEN];
129 int (*
const format_log)(
struct logchannel *channel,
struct logmsg *msg,
char *buf,
size_t size);
173 enum logmsgtypes
type;
179 unsigned int hidecli:1;
190 static
void logmsg_free(struct
logmsg *msg)
197 static pthread_t logthread = AST_PTHREADT_NULL;
198 static ast_cond_t logcond;
199 static int close_logger_thread = 0;
234 static const int colors[NUMLOGLEVELS] = {
271 #define VERBOSE_BUF_INIT_SIZE 256
274 #define LOG_BUF_INIT_SIZE 256
276 static int format_log_json(
struct logchannel *channel,
struct logmsg *msg,
char *buf,
size_t size)
280 char call_identifier_str[13];
284 snprintf(call_identifier_str,
sizeof(call_identifier_str),
"[C-%08x]", msg->callid);
286 call_identifier_str[0] =
'\0';
291 "s: {s: {s: s, s: s, s: i}, "
293 "hostname", ast_config_AST_SYSTEM_NAME,
294 "timestamp", msg->date,
297 "callid",
S_OR(call_identifier_str,
""),
300 "filename", msg->file,
301 "function", msg->function,
303 "level", msg->level_name,
304 "message", msg->message);
316 json_str_len = strlen(str);
317 if (json_str_len > size - 1) {
318 json_str_len = size - 1;
320 buf[json_str_len] =
'\n';
321 buf[json_str_len + 1] =
'\0';
333 .format_log = format_log_json
336 static int logger_add_verbose_magic(
struct logmsg *
logmsg,
char *buf,
size_t size)
341 signed char magic = logmsg->sublevel > 9 ? -10 : -logmsg->sublevel - 1;
344 if (logmsg->sublevel < 0) {
345 if (!strncmp(logmsg->message, VERBOSE_PREFIX_10, strlen(VERBOSE_PREFIX_10))) {
347 }
else if (!strncmp(logmsg->message, VERBOSE_PREFIX_9, strlen(VERBOSE_PREFIX_9))) {
349 }
else if (!strncmp(logmsg->message, VERBOSE_PREFIX_8, strlen(VERBOSE_PREFIX_8))) {
351 }
else if (!strncmp(logmsg->message, VERBOSE_PREFIX_7, strlen(VERBOSE_PREFIX_7))) {
353 }
else if (!strncmp(logmsg->message, VERBOSE_PREFIX_6, strlen(VERBOSE_PREFIX_6))) {
355 }
else if (!strncmp(logmsg->message, VERBOSE_PREFIX_5, strlen(VERBOSE_PREFIX_5))) {
357 }
else if (!strncmp(logmsg->message, VERBOSE_PREFIX_4, strlen(VERBOSE_PREFIX_4))) {
359 }
else if (!strncmp(logmsg->message, VERBOSE_PREFIX_3, strlen(VERBOSE_PREFIX_3))) {
361 }
else if (!strncmp(logmsg->message, VERBOSE_PREFIX_2, strlen(VERBOSE_PREFIX_2))) {
363 }
else if (!strncmp(logmsg->message, VERBOSE_PREFIX_1, strlen(VERBOSE_PREFIX_1))) {
377 fmt = logmsg->message;
379 if (!(p = strchr(fmt,
'\n'))) {
380 p = strchr(fmt,
'\0') - 1;
394 static int format_log_default(
struct logchannel *chan,
struct logmsg *msg,
char *buf,
size_t size)
396 char call_identifier_str[13];
399 snprintf(call_identifier_str,
sizeof(call_identifier_str),
"[C-%08x]", msg->callid);
401 call_identifier_str[0] =
'\0';
404 switch (chan->
type) {
406 snprintf(buf, size,
"%s[%d]%s: %s:%d in %s: %s",
407 levels[msg->level], msg->lwp, call_identifier_str, msg->file,
408 msg->line, msg->function, msg->message);
412 snprintf(buf, size,
"[%s] %s[%d]%s %s: %s",
413 msg->date, msg->level_name, msg->lwp, call_identifier_str,
414 msg->file, msg->message);
417 case LOGTYPE_CONSOLE:
420 int has_file = !ast_strlen_zero(msg->file);
421 int has_line = (msg->line > 0);
422 int has_func = !ast_strlen_zero(msg->function);
428 if (msg->level == __LOG_VERBOSE) {
429 return logger_add_verbose_magic(msg, buf, size);
433 snprintf(linestr,
sizeof(linestr),
"%d", msg->line);
437 COLORIZE(colors[msg->level], 0, msg->level_name),
440 COLORIZE(COLOR_BRWHITE, 0, has_file ? msg->file :
""),
442 COLORIZE(COLOR_BRWHITE, 0, has_line ? linestr :
""),
443 COLORIZE(COLOR_BRWHITE, 0, has_func ? msg->function :
""),
455 .format_log = format_log_default,
458 static int format_log_plain(
struct logchannel *chan,
struct logmsg *msg,
char *buf,
size_t size)
460 char call_identifier_str[13];
462 int has_file = !ast_strlen_zero(msg->file);
463 int has_line = (msg->line > 0);
464 int has_func = !ast_strlen_zero(msg->function);
467 snprintf(call_identifier_str,
sizeof(call_identifier_str),
"[C-%08x]", msg->callid);
469 call_identifier_str[0] =
'\0';
472 switch (chan->
type) {
474 snprintf(buf, size,
"%s[%d]%s: %s:%d in %s: %s",
475 levels[msg->level], msg->lwp, call_identifier_str, msg->file,
476 msg->line, msg->function, msg->message);
480 case LOGTYPE_CONSOLE:
482 snprintf(linestr,
sizeof(linestr),
"%d", msg->line);
484 snprintf(buf, size,
"[%s] %s[%d]%s: %s%s%s%s%s%s%s",
489 has_file ? msg->file :
"",
491 has_line ? linestr :
"",
493 has_func ? msg->function :
"",
494 has_func ?
": " :
"",
505 .format_log = format_log_plain,
508 static void make_components(
struct logchannel *chan)
511 unsigned int logmask = 0;
514 unsigned int verb_level;
519 w = strchr(stringp,
'[');
521 char *end = strchr(w + 1,
']');
523 fprintf(stderr,
"Logger Warning: bad formatter definition for %s in logger.conf\n", chan->
filename);
525 char *formatter_name = w + 1;
530 if (!strcasecmp(formatter_name,
"json")) {
532 }
else if (!strcasecmp(formatter_name,
"default")) {
534 }
else if (!strcasecmp(formatter_name,
"plain")) {
537 fprintf(stderr,
"Logger Warning: Unknown formatter definition %s for %s in logger.conf; using 'default'\n",
548 while ((w = strsep(&stringp,
","))) {
550 if (ast_strlen_zero(w)) {
553 if (!strcmp(w,
"*")) {
554 logmask = 0xFFFFFFFF;
555 }
else if (!strncasecmp(w,
"verbose(", 8)) {
556 if (levels[__LOG_VERBOSE] && sscanf(w + 8,
"%30u)", &verb_level) == 1) {
557 logmask |= (1 << __LOG_VERBOSE);
560 for (x = 0; x < ARRAY_LEN(levels); ++x) {
561 if (levels[x] && !strcasecmp(w, levels[x])) {
568 if (chan->
type == LOGTYPE_CONSOLE) {
575 logmask |= (1 << __LOG_VERBOSE);
591 const char *log_dir_prefix =
"";
592 const char *log_dir_separator =
"";
596 if (!strcasecmp(channel,
"console")) {
600 if (!strncasecmp(channel,
"syslog", 6)) {
607 if (channel[0] !=
'/') {
608 log_dir_prefix = ast_config_AST_LOG_DIR;
609 log_dir_separator =
"/";
612 if (!ast_strlen_zero(hostname)) {
613 snprintf(filename, size,
"%s%s%s.%s",
614 log_dir_prefix, log_dir_separator, channel, hostname);
616 snprintf(filename, size,
"%s%s%s",
617 log_dir_prefix, log_dir_separator, channel);
632 char filename[PATH_MAX];
638 if (!strcmp(chan->
filename, filename)) {
652 char datestring[256];
654 if (ast_strlen_zero(channel) || !(chan =
ast_calloc(1,
sizeof(*chan) + strlen(components) + 1)))
663 if (!strcasecmp(channel,
"console")) {
664 chan->
type = LOGTYPE_CONSOLE;
665 }
else if (!strncasecmp(channel,
"syslog", 6)) {
670 facility = strchr(channel,
'.');
671 if (!facility++ || !facility) {
678 fprintf(stderr,
"Logger Warning: bad syslog facility in logger.conf\n");
683 chan->
type = LOGTYPE_SYSLOG;
684 openlog(
"asterisk", LOG_PID, chan->
facility);
699 ast_strftime(datestring,
sizeof(datestring), dateformat, &tm);
701 fprintf(chan->
fileptr,
"[%s] Asterisk %s built by %s @ %s on a %s running %s on %s\n",
703 ast_build_machine, ast_build_os, ast_build_date);
706 chan->
type = LOGTYPE_FILE;
708 make_components(chan);
719 if (!(cfg =
ast_config_load2(
"logger.conf",
"logger", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
723 if ((s = ast_variable_retrieve(cfg,
"general",
"dateformat"))) {
742 for (i = 0; i < len; i++) {
743 if (!strcmp(levels[i], level)) {
767 if (!(cfg =
ast_config_load2(
S_OR(altconf,
"logger.conf"),
"logger", config_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
774 memset(&logfiles, 0,
sizeof(logfiles));
775 logfiles.queue_log = 1;
778 exec_after_rotate[0] =
'\0';
779 rotatestrategy = SEQUENTIAL;
793 chan = make_logchannel(
"console",
"error,warning,notice,verbose", 0, 0);
795 fprintf(stderr,
"ERROR: Failed to initialize default logging\n");
800 global_logmask |= chan->
logmask;
805 if ((s = ast_variable_retrieve(cfg,
"general",
"appendhostname"))) {
807 if (gethostname(hostname,
sizeof(hostname) - 1)) {
809 fprintf(stderr,
"What box has no hostname???\n");
813 if ((s = ast_variable_retrieve(cfg,
"general",
"display_callids"))) {
816 if ((s = ast_variable_retrieve(cfg,
"general",
"dateformat"))) {
819 if ((s = ast_variable_retrieve(cfg,
"general",
"queue_log"))) {
822 if ((s = ast_variable_retrieve(cfg,
"general",
"queue_log_to_file"))) {
823 logfiles.queue_log_to_file =
ast_true(s);
825 if ((s = ast_variable_retrieve(cfg,
"general",
"queue_log_name"))) {
828 if ((s = ast_variable_retrieve(cfg,
"general",
"queue_log_realtime_use_gmt"))) {
829 logfiles.queue_log_realtime_use_gmt =
ast_true(s);
831 if ((s = ast_variable_retrieve(cfg,
"general",
"exec_after_rotate"))) {
834 if ((s = ast_variable_retrieve(cfg,
"general",
"rotatestrategy"))) {
835 if (strcasecmp(s,
"timestamp") == 0) {
836 rotatestrategy = TIMESTAMP;
837 }
else if (strcasecmp(s,
"rotate") == 0) {
838 rotatestrategy = ROTATE;
839 }
else if (strcasecmp(s,
"sequential") == 0) {
840 rotatestrategy = SEQUENTIAL;
841 }
else if (strcasecmp(s,
"none") == 0) {
842 rotatestrategy = NONE;
844 fprintf(stderr,
"Unknown rotatestrategy: %s\n", s);
847 if ((s = ast_variable_retrieve(cfg,
"general",
"rotatetimestamp"))) {
848 rotatestrategy =
ast_true(s) ? TIMESTAMP : SEQUENTIAL;
849 fprintf(stderr,
"rotatetimestamp option has been deprecated. Please use rotatestrategy instead.\n");
852 if ((s = ast_variable_retrieve(cfg,
"general",
"logger_queue_limit"))) {
853 if (sscanf(s,
"%30d", &logger_queue_limit) != 1) {
854 fprintf(stderr,
"logger_queue_limit has an invalid value. Leaving at default of %d.\n",
857 if (logger_queue_limit < 10) {
858 fprintf(stderr,
"logger_queue_limit must be >= 10. Setting to 10.\n");
859 logger_queue_limit = 10;
864 if ((s = ast_variable_retrieve(cfg,
"general",
"custom_levels"))) {
867 char *new_custom_levels[16] = { };
868 unsigned int level, new_level = 0;
871 while ((logfile = strsep(&customlogs,
","))) {
872 new_custom_levels[new_level++] = logfile;
877 for (level = 16; level < ARRAY_LEN(levels); level++) {
878 if (levels[level] && custom_dynamic_levels[level] &&
880 logger_unregister_level(levels[level]);
881 custom_dynamic_levels[level] = 0;
886 while ((logfile = new_custom_levels[new_level++])) {
889 if (logger_get_dynamic_level(logfile) == -1) {
890 int custom_level = logger_register_level(logfile);
891 custom_dynamic_levels[custom_level] = logfile;
896 var = ast_variable_browse(cfg,
"logfiles");
897 for (; var; var = var->
next) {
898 chan = make_logchannel(var->
name, var->
value, var->lineno, 0);
908 global_logmask |= chan->
logmask;
921 void ast_child_verbose(
int level,
const char *fmt, ...)
923 char *msg = NULL, *emsg = NULL, *sptr, *eptr;
929 if ((size = vsnprintf(msg, 0, fmt, ap)) < 0) {
941 vsnprintf(msg, size + 1, fmt, aq);
949 for (sptr = msg, eptr = emsg; ; sptr++) {
960 fprintf(stdout,
"verbose \"%s\" %d\n", emsg, level);
965 void ast_queue_log(
const char *queuename,
const char *callid,
const char *agent,
const char *
event,
const char *fmt, ...)
974 if (!logger_initialized) {
978 if (!queuelog_init) {
985 ast_localtime(&tv, &tm, logfiles.queue_log_realtime_use_gmt ?
"GMT" : NULL);
986 ast_strftime(time_str,
sizeof(time_str),
"%F %T.%6q", &tm);
988 vsnprintf(qlog_msg,
sizeof(qlog_msg), fmt, ap);
990 if (logfiles.queue_adaptive_realtime) {
997 "data1", RQ_CHAR, strlen(
S_OR(args.data[0],
"")),
998 "data2", RQ_CHAR, strlen(
S_OR(args.data[1],
"")),
999 "data3", RQ_CHAR, strlen(
S_OR(args.data[2],
"")),
1000 "data4", RQ_CHAR, strlen(
S_OR(args.data[3],
"")),
1001 "data5", RQ_CHAR, strlen(
S_OR(args.data[4],
"")),
1007 "queuename", queuename,
1010 "data1",
S_OR(args.data[0],
""),
1011 "data2",
S_OR(args.data[1],
""),
1012 "data3",
S_OR(args.data[2],
""),
1013 "data4",
S_OR(args.data[3],
""),
1014 "data5",
S_OR(args.data[4],
""),
1019 "queuename", queuename,
1026 if (!logfiles.queue_log_to_file) {
1033 qlog_len = snprintf(qlog_msg,
sizeof(qlog_msg),
"%ld|%s|%s|%s|%s|", (
long)time(NULL), callid, queuename, agent, event);
1034 vsnprintf(qlog_msg + qlog_len,
sizeof(qlog_msg) - qlog_len, fmt, ap);
1038 fprintf(qlog,
"%s\n", qlog_msg);
1045 static int rotate_file(
const char *filename)
1049 int x, y, which, found, res = 0, fd;
1050 char *suffixes[4] = {
"",
".gz",
".bz2",
".Z" };
1052 switch (rotatestrategy) {
1057 for (x = 0; ; x++) {
1058 snprintf(
new,
sizeof(
new),
"%s.%d", filename, x);
1059 fd = open(
new, O_RDONLY);
1065 if (rename(filename,
new)) {
1066 fprintf(stderr,
"Unable to rename file '%s' to '%s'\n", filename,
new);
1073 snprintf(
new,
sizeof(
new),
"%s.%ld", filename, (
long)time(NULL));
1074 if (rename(filename,
new)) {
1075 fprintf(stderr,
"Unable to rename file '%s' to '%s'\n", filename,
new);
1083 for (x = 0; ; x++) {
1085 for (which = 0; which < ARRAY_LEN(suffixes); which++) {
1086 snprintf(
new,
sizeof(
new),
"%s.%d%s", filename, x, suffixes[which]);
1087 fd = open(
new, O_RDONLY);
1100 for (y = x; y > 0; y--) {
1101 for (which = 0; which < ARRAY_LEN(suffixes); which++) {
1102 snprintf(old,
sizeof(old),
"%s.%d%s", filename, y - 1, suffixes[which]);
1103 fd = open(old, O_RDONLY);
1107 snprintf(
new,
sizeof(
new),
"%s.%d%s", filename, y, suffixes[which]);
1108 if (rename(old,
new)) {
1109 fprintf(stderr,
"Unable to rename file '%s' to '%s'\n", old,
new);
1118 snprintf(
new,
sizeof(
new),
"%s.0", filename);
1119 if (rename(filename,
new)) {
1120 fprintf(stderr,
"Unable to rename file '%s' to '%s'\n", filename,
new);
1127 if (!ast_strlen_zero(exec_after_rotate)) {
1132 pbx_substitute_variables_helper(c, exec_after_rotate, buf,
sizeof(buf));
1137 ast_log(LOG_WARNING,
"error executing '%s'\n", buf);
1149 static int logger_queue_rt_start(
void)
1153 "time", RQ_DATETIME, 26,
1154 "data1", RQ_CHAR, 20,
1155 "data2", RQ_CHAR, 20,
1156 "data3", RQ_CHAR, 20,
1157 "data4", RQ_CHAR, 20,
1158 "data5", RQ_CHAR, 20,
1160 logfiles.queue_adaptive_realtime = 1;
1162 logfiles.queue_adaptive_realtime = 0;
1165 if (!logfiles.queue_log_to_file) {
1184 static int logger_queue_restart(
int queue_rotate)
1187 char qfname[PATH_MAX];
1189 if (logger_queue_rt_start()) {
1193 snprintf(qfname,
sizeof(qfname),
"%s/%s", ast_config_AST_LOG_DIR, queue_log_name);
1200 rotate_file(qfname);
1204 qlog = fopen(qfname,
"a");
1206 ast_log(LOG_ERROR,
"Unable to create queue log: %s\n", strerror(errno));
1212 static int reload_logger(
int rotate,
const char *altconf)
1214 int queue_rotate = rotate;
1223 if (ftello(qlog) > 0x40000000) {
1237 ast_mkdir(ast_config_AST_LOG_DIR, 0777);
1257 int rotate_this = 0;
1258 if (rotatestrategy != NONE && ftello(f->
fileptr) > 0x40000000) {
1264 if (rotate || rotate_this) {
1270 filesize_reload_needed = 0;
1275 if (logfiles.queue_log) {
1276 res = logger_queue_restart(queue_rotate);
1279 ast_queue_log(
"NONE",
"NONE",
"NONE",
"CONFIGRELOAD",
"%s",
"");
1280 ast_verb(1,
"Asterisk Queue Logger restarted\n");
1295 "Usage: logger reload [<alt-conf>]\n"
1296 " Reloads the logger subsystem state. Use after restarting syslogd(8) if you are using syslog logging.\n";
1301 if (reload_logger(0, a->argc == 3 ? a->argv[2] : NULL)) {
1302 ast_cli(a->fd,
"Failed to reload the logger\n");
1314 "Usage: logger rotate\n"
1315 " Rotates and Reopens the log files.\n";
1320 if (reload_logger(1, NULL)) {
1321 ast_cli(a->fd,
"Failed to reload the logger and rotate log files\n");
1329 return reload_logger(1, NULL);
1336 char filename[PATH_MAX];
1342 ast_mkdir(ast_config_AST_LOG_DIR, 0644);
1347 manager_event(EVENT_FLAG_SYSTEM,
"LogChannel",
"Channel: %s\r\nEnabled: Yes\r\n",
1353 if (strcmp(filename, f->
filename) == 0) {
1375 e->
command =
"logger set level {DEBUG|TRACE|NOTICE|WARNING|ERROR|VERBOSE|DTMF} {on|off}";
1377 "Usage: logger set level {DEBUG|TRACE|NOTICE|WARNING|ERROR|VERBOSE|DTMF} {on|off}\n"
1378 " Set a specific log level to enabled/disabled for this console.\n";
1385 return CLI_SHOWUSAGE;
1389 for (x = 0; x < ARRAY_LEN(levels); x++) {
1390 if (levels[x] && !strcasecmp(a->argv[3], levels[x])) {
1398 state =
ast_true(a->argv[4]) ? 1 : 0;
1402 ast_cli(a->fd,
"Logger status for '%s' has been set to '%s'.\n", levels[level], state ?
"on" :
"off");
1404 return CLI_SHOWUSAGE;
1410 const char *status,
const char *configuration,
void *data),
void *data)
1426 for (level = 0; level < ARRAY_LEN(levels); level++) {
1427 if ((chan->
logmask & (1 << level)) && levels[level]) {
1432 res = logentry(chan->
filename, chan->
type == LOGTYPE_CONSOLE ?
"Console" :
1433 (chan->
type == LOGTYPE_SYSLOG ?
"Syslog" :
"File"), chan->
disabled ?
1454 #define FORMATL "%-35.35s %-8.8s %-10.10s %-9.9s "
1458 e->
command =
"logger show channels";
1460 "Usage: logger show channels\n"
1461 " List configured logger channels.\n";
1466 ast_cli(a->fd,
"Logger queue limit: %d\n\n", logger_queue_limit);
1467 ast_cli(a->fd, FORMATL,
"Channel",
"Type",
"Formatter",
"Status");
1468 ast_cli(a->fd,
"Configuration\n");
1469 ast_cli(a->fd, FORMATL,
"-------",
"----",
"---------",
"------");
1470 ast_cli(a->fd,
"-------------\n");
1475 ast_cli(a->fd, FORMATL, chan->
filename, chan->
type == LOGTYPE_CONSOLE ?
"Console" : (chan->
type == LOGTYPE_SYSLOG ?
"Syslog" :
"File"),
1477 chan->
disabled ?
"Disabled" :
"Enabled");
1478 ast_cli(a->fd,
" - ");
1479 for (level = 0; level < ARRAY_LEN(levels); level++) {
1480 if ((chan->
logmask & (1 << level)) && levels[level]) {
1481 ast_cli(a->fd,
"%s ", levels[level]);
1484 ast_cli(a->fd,
"\n");
1487 ast_cli(a->fd,
"\n");
1495 #define FORMATL2 "%5s %s\n"
1499 e->
command =
"logger show levels";
1501 "Usage: logger show levels\n"
1502 " List configured logger levels.\n";
1507 ast_cli(a->fd, FORMATL2,
"Level",
"Name");
1508 ast_cli(a->fd, FORMATL2,
"-----",
"----");
1510 for (level = 0; level < ARRAY_LEN(levels); level++) {
1511 if (levels[level]) {
1512 ast_cli(a->fd,
"%5d %s\n", level, levels[level]);
1516 ast_cli(a->fd,
"\n");
1525 if (ast_strlen_zero(components)) {
1537 chan = make_logchannel(log_channel, components, 0, 1);
1544 global_logmask |= chan->
logmask;
1555 e->
command =
"logger add channel";
1557 "Usage: logger add channel <name> <levels>\n"
1558 " Adds a temporary logger channel. This logger channel\n"
1559 " will exist until removed or until Asterisk is restarted.\n"
1560 " <levels> is a comma-separated list of desired logger\n"
1561 " levels such as: verbose,warning,error\n"
1562 " An optional formatter may be specified with the levels;\n"
1563 " valid values are '[json]' and '[default]'.\n";
1570 return CLI_SHOWUSAGE;
1577 ast_cli(a->fd,
"Logger channel '%s' already exists\n", a->argv[3]);
1582 ast_cli(a->fd,
"ERROR: Unable to create log channel '%s'\n", a->argv[3]);
1616 char *gen_ret = NULL;
1620 e->
command =
"logger remove channel";
1622 "Usage: logger remove channel <name>\n"
1623 " Removes a temporary logger channel.\n";
1626 if (a->argc > 4 || (a->argc == 4 && a->pos > 3)) {
1631 if (chan->
dynamic && (ast_strlen_zero(a->argv[3])
1632 || !strncmp(a->argv[3], chan->
filename, strlen(a->argv[3])))) {
1633 if (gen_count == a->n) {
1645 return CLI_SHOWUSAGE;
1650 ast_cli(a->fd,
"Removed dynamic logger channel '%s'\n", a->argv[3]);
1653 ast_cli(a->fd,
"Unable to find dynamic logger channel '%s'\n", a->argv[3]);
1656 ast_cli(a->fd,
"Internal failure attempting to delete dynamic logger channel '%s'\n", a->argv[3]);
1673 static int callid_filtering = 0;
1675 static const char *get_callid_group(
void)
1677 char **callid_group;
1679 return callid_group ? *callid_group : NULL;
1682 static int callid_set_chanloggroup(
const char *
group)
1686 char **callid_group;
1699 if (!*callid_group) {
1702 ast_free(*callid_group);
1706 ast_free(*callid_group);
1708 if (!*callid_group) {
1714 static int callid_group_remove_filters(
void)
1724 callid_filtering = 0;
1729 static int callid_group_set_filter(
const char *group,
int enabled)
1735 if (!strcmp(group, cgl->name)) {
1737 AST_RWLIST_REMOVE_CURRENT(
entry);
1743 AST_RWLIST_TRAVERSE_SAFE_END;
1747 callid_filtering = 0;
1754 cgl =
ast_calloc(1,
sizeof(*cgl) + strlen(group) + 1);
1759 strcpy(cgl->name, group);
1762 callid_filtering = 1;
1767 static int callid_logging_enabled(
void)
1770 const char *callidgroup;
1772 if (!callid_filtering) {
1776 callidgroup = get_callid_group();
1783 if (!strcmp(callidgroup, cgl->name)) {
1791 static int log_group_write(
struct ast_channel *chan,
const char *cmd,
char *data,
const char *value)
1793 int res = callid_set_chanloggroup(value);
1795 ast_log(LOG_ERROR,
"Failed to set channel log group for %s\n", ast_channel_name(chan));
1802 .
name =
"LOG_GROUP",
1803 .write = log_group_write,
1812 e->
command =
"logger filter changroup";
1814 "Usage: logger filter changroup <group> {on|off}\n"
1815 " Add or remove channel groups from log filtering.\n"
1816 " If filtering is active, only channels assigned\n"
1817 " to a group that has been enabled using this command\n"
1818 " will have execution shown in the CLI.\n";
1825 return CLI_SHOWUSAGE;
1828 enabled =
ast_true(a->argv[4]) ? 1 : 0;
1829 if (callid_group_set_filter(a->argv[3], enabled)) {
1830 ast_cli(a->fd,
"Failed to set channel group filter for group %s\n", a->argv[3]);
1834 ast_cli(a->fd,
"Logging of channel group '%s' is now %s\n", a->argv[3], enabled ?
"enabled" :
"disabled");
1845 e->
command =
"logger filter show";
1847 "Usage: logger filter show\n"
1848 " Show current logger filtering settings.\n";
1856 ast_cli(a->fd,
"%3d %-32s\n", ++i, cgl->name);
1861 ast_cli(a->fd,
"%d channel group%s currently enabled\n", i,
ESS(i));
1863 ast_cli(a->fd,
"No filtering currently active\n");
1874 e->
command =
"logger filter reset";
1876 "Usage: logger filter reset\n"
1877 " Reset the logger filter.\n"
1878 " This removes any channel groups from filtering\n"
1879 " (all channel execution will be shown)\n";
1885 removed = callid_group_remove_filters();
1887 ast_cli(a->fd,
"Log filtering has been reset (%d filter%s removed)\n", removed,
ESS(removed));
1894 AST_CLI_DEFINE(handle_logger_reload,
"Reopens the log files"),
1895 AST_CLI_DEFINE(handle_logger_rotate,
"Rotates and reopens the log files"),
1896 AST_CLI_DEFINE(handle_logger_set_level,
"Enables/Disables a specific logging level for this console"),
1897 AST_CLI_DEFINE(handle_logger_add_channel,
"Adds a new logging channel"),
1898 AST_CLI_DEFINE(handle_logger_remove_channel,
"Removes a logging channel"),
1899 AST_CLI_DEFINE(handle_logger_chanloggroup_filter,
"Filter PBX logs by channel log group"),
1900 AST_CLI_DEFINE(handle_logger_filter_show,
"Show current PBX channel filtering"),
1901 AST_CLI_DEFINE(handle_logger_filter_reset,
"Reset PBX channel filtering"),
1904 static void _handle_SIGXFSZ(
int sig)
1907 filesize_reload_needed = 1;
1910 static struct sigaction handle_SIGXFSZ = {
1911 .sa_handler = _handle_SIGXFSZ,
1912 .sa_flags = SA_RESTART,
1919 char buf[LOGMSG_SIZE];
1930 if (logmsg->level == __LOG_VERBOSE
1935 if (!(chan->
logmask & (1 << logmsg->level))) {
1939 switch (chan->
type) {
1940 case LOGTYPE_SYSLOG:
1944 if (syslog_level < 0) {
1946 fprintf(stderr,
"ast_log_vsyslog called with bogus level: %d\n", logmsg->level);
1951 syslog_level = chan->
facility | syslog_level;
1952 if (!chan->
formatter.format_log(chan, logmsg, buf,
sizeof(buf))) {
1953 syslog(syslog_level,
"%s", buf);
1957 case LOGTYPE_CONSOLE:
1958 if (!logmsg->
hidecli && !chan->
formatter.format_log(chan, logmsg, buf,
sizeof(buf))) {
1970 if (chan->
formatter.format_log(chan, logmsg, buf,
sizeof(buf))) {
1975 res = fprintf(chan->
fileptr,
"%s", buf);
1978 }
else if (res <= 0 && !ast_strlen_zero(logmsg->message)) {
1979 fprintf(stderr,
"**** Asterisk Logging Error: ***********\n");
1980 if (errno == ENOMEM || errno == ENOSPC) {
1981 fprintf(stderr,
"Asterisk logging error: Out of disk space, can't log to log file %s\n", chan->
filename);
1983 fprintf(stderr,
"Logger Warning: Unable to write to log file '%s': %s (disabled)\n", chan->
filename, strerror(errno));
1996 manager_event(EVENT_FLAG_SYSTEM,
"LogChannel",
"Channel: %s\r\nEnabled: No\r\nReason: %d - %s\r\n", chan->
filename, errno, strerror(errno));
2003 }
else if (logmsg->level != __LOG_VERBOSE ||
option_verbose >= logmsg->sublevel) {
2004 fputs(logmsg->message, stdout);
2010 if (filesize_reload_needed) {
2011 reload_logger(-1, NULL);
2012 ast_verb(1,
"Rotated Logs Per SIGXFSZ (Exceeded file size limit)\n");
2018 static struct logmsg * __attribute__((format(printf, 7, 0))) format_log_message_ap(
int level,
2019 int sublevel, const
char *file,
int line, const
char *function, ast_callid callid,
2020 const
char *fmt, va_list ap)
2022 struct logmsg *logmsg = NULL;
2027 char datestring[256];
2055 if (level == __LOG_VERBOSE) {
2056 logmsg->type = LOGMSG_VERBOSE;
2058 logmsg->type = LOGMSG_NORMAL;
2061 if (display_callids && callid) {
2062 logmsg->callid = callid;
2067 ast_strftime(datestring,
sizeof(datestring), dateformat, &tm);
2071 logmsg->level = level;
2072 logmsg->sublevel = sublevel;
2073 logmsg->line = line;
2082 static struct logmsg * __attribute__((format(printf, 7, 0))) format_log_message(
int level,
2083 int sublevel, const
char *file,
int line, const
char *function, ast_callid callid,
2084 const
char *fmt, ...)
2086 struct logmsg *logmsg;
2090 logmsg = format_log_message_ap(level, sublevel, file, line,
function, callid, fmt, ap);
2099 struct logmsg *next = NULL, *msg = NULL;
2105 if (close_logger_thread) {
2109 ast_cond_wait(&logcond, &
logmsgs.lock);
2113 if (high_water_alert) {
2114 msg = format_log_message(__LOG_WARNING, 0,
"logger", 0,
"***", 0,
2115 "Logging resumed. %d message%s discarded.\n",
2116 logger_messages_discarded, logger_messages_discarded == 1 ?
"" :
"s");
2120 high_water_alert = 0;
2121 logger_messages_discarded = 0;
2126 logger_queue_size = 0;
2130 while ((msg = next)) {
2151 static void logger_queue_init(
void)
2154 if (logfiles.queue_log) {
2155 char qfname[PATH_MAX];
2157 if (logger_queue_rt_start()) {
2162 snprintf(qfname,
sizeof(qfname),
"%s/%s", ast_config_AST_LOG_DIR,
2168 qlog = fopen(qfname,
"a");
2170 ast_log(LOG_ERROR,
"Unable to create queue log: %s\n", strerror(errno));
2177 return logger_initialized;
2189 ast_assert(logger_initialized);
2192 if (!queuelog_init) {
2193 logger_queue_init();
2196 ast_queue_log(
"NONE",
"NONE",
"NONE",
"QUEUESTART",
"%s",
"");
2206 sigaction(SIGXFSZ, &handle_SIGXFSZ, NULL);
2214 ast_mutex_destroy(&
logmsgs.lock);
2215 ast_mutex_init(&
logmsgs.lock);
2216 ast_cond_init(&logcond, NULL);
2219 if (ast_pthread_create(&logthread, NULL,
logger_thread, NULL) < 0) {
2220 ast_cond_destroy(&logcond);
2228 ast_mkdir(ast_config_AST_LOG_DIR, 0777);
2235 logger_initialized = 1;
2237 ast_log(LOG_ERROR,
"Errors detected in logger.conf. Default console logging is being used.\n");
2240 ast_logger_category_load();
2249 ast_logger_category_unload();
2254 logger_initialized = 0;
2258 close_logger_thread = 1;
2259 ast_cond_signal(&logcond);
2262 if (logthread != AST_PTHREADT_NULL) {
2263 pthread_join(logthread, NULL);
2281 callid_group_remove_filters();
2290 snprintf(buffer, buffer_size,
"[C-%08x]", callid);
2304 return callid ? *callid : 0;
2322 ast_callid *pointing;
2330 ast_log(LOG_ERROR,
"ast_callid_threadassoc_add(C-%08x) on thread "
2331 "already associated with callid [C-%08x].\n", callid, *pointing);
2341 ast_callid *pointing;
2380 if (callid && callid_created) {
2389 static void __attribute__((format(printf, 7, 0)))
ast_log_full(
int level,
int sublevel,
2390 const
char *file,
int line, const
char *function, ast_callid callid,
2391 const
char *fmt, va_list ap)
2394 struct logmsg *logmsg = NULL;
2396 if (level == __LOG_VERBOSE && ast_opt_remote && ast_opt_exec) {
2400 if (callid_filtering && !callid_logging_enabled()) {
2414 if (logger_queue_size >= logger_queue_limit && !close_logger_thread) {
2415 logger_messages_discarded++;
2416 if (!high_water_alert && !close_logger_thread) {
2417 logmsg = format_log_message(__LOG_WARNING, 0,
"logger", 0,
"***", 0,
2418 "Log queue threshold (%d) exceeded. Discarding new messages.\n", logger_queue_limit);
2420 high_water_alert = 1;
2421 ast_cond_signal(&logcond);
2428 logmsg = format_log_message_ap(level, sublevel, file, line,
function, callid, fmt, ap);
2436 if (logthread != AST_PTHREADT_NULL) {
2438 if (close_logger_thread) {
2440 logmsg_free(logmsg);
2443 logger_queue_size++;
2444 ast_cond_signal(&logcond);
2449 logmsg_free(logmsg);
2453 void ast_log(
int level,
const char *file,
int line,
const char *
function,
const char *fmt, ...)
2458 ast_log_ap(level, file, line,
function, fmt, ap);
2462 void ast_log_ap(
int level,
const char *file,
int line,
const char *
function,
const char *fmt, va_list ap)
2468 if (level == __LOG_VERBOSE) {
2469 __ast_verbose_ap(file, line,
function, 0, callid, fmt, ap);
2471 ast_log_full(level, -1, file, line,
function, callid, fmt, ap);
2475 void ast_log_safe(
int level,
const char *file,
int line,
const char *
function,
const char *fmt, ...)
2494 ast_log_full(level, -1, file, line,
function, callid, fmt, ap);
2501 void ast_log_callid(
int level,
const char *file,
int line,
const char *
function, ast_callid callid,
const char *fmt, ...)
2505 ast_log_full(level, -1, file, line,
function, callid, fmt, ap);
2517 if (!(bt = ast_bt_create())) {
2518 ast_log(LOG_WARNING,
"Unable to allocate space for backtrace structure\n");
2527 ast_str_append(&buf, 0,
"Got %d backtrace record%c\n", count - 3, count - 3 != 1 ?
's' :
' ');
2535 ast_bt_free_symbols(strings);
2537 ast_log(LOG_ERROR,
"Could not allocate memory for backtrace\n");
2541 ast_log(LOG_WARNING,
"Must run configure with '--with-execinfo' for stack backtraces.\n");
2545 void __ast_verbose_ap(
const char *file,
int line,
const char *func,
int level, ast_callid callid,
const char *fmt, va_list ap)
2547 ast_log_full(__LOG_VERBOSE, level, file, line, func, callid, fmt, ap);
2550 void __ast_verbose(
const char *file,
int line,
const char *func,
int level,
const char *fmt, ...)
2558 __ast_verbose_ap(file, line, func, level, callid, fmt, ap);
2562 void __ast_verbose_callid(
const char *file,
int line,
const char *func,
int level, ast_callid callid,
const char *fmt, ...)
2566 __ast_verbose_ap(file, line, func, level, callid, fmt, ap);
2599 if (verb_level < *console->level) {
2600 verb_level = *console->
level;
2608 if (verb_level < log->verbosity) {
2635 static void verb_console_free(
void *v_console)
2639 verb_console_unregister(console);
2651 if (!console || !level) {
2670 verb_console_unregister(console);
2682 }
else if (console->
level) {
2683 verb_level = *console->
level;
2701 if (console->
level) {
2702 *console->
level = verb_level;
2710 static void update_logchannels(
void)
2717 make_components(cur);
2718 global_logmask |= cur->
logmask;
2725 #define LOTS_O_SPACES " "
2727 unsigned long _ast_trace_get_indent(
void)
2732 void _ast_trace_set_indent(
unsigned long indent)
2737 unsigned long _ast_trace_inc_indent(
void)
2746 unsigned long _ast_trace_dec_indent(
void)
2755 void __ast_trace(
const char *file,
int line,
const char *func,
enum ast_trace_indent_type indent_type,
2756 unsigned long new_indent,
const char* format, ...)
2761 const char *direction =
"";
2768 indent = new_indent;
2778 switch(indent_type) {
2806 va_start(ap, format);
2814 static int logger_register_level(
const char *name)
2817 unsigned int available = 0;
2819 for (level = 0; level < ARRAY_LEN(levels); level++) {
2820 if ((level >= 16) && !available && !levels[level]) {
2825 if (levels[level] && !strcasecmp(levels[level], name)) {
2827 "Unable to register dynamic logger level '%s': a standard logger level uses that name.\n",
2836 "Unable to register dynamic logger level '%s'; maximum number of levels registered.\n",
2844 ast_debug(1,
"Registered dynamic logger level '%s' with index %u.\n", name, available);
2846 update_logchannels();
2856 available = logger_register_level(name);
2862 static int logger_get_dynamic_level(
const char *name)
2867 for (x = 16; x < ARRAY_LEN(levels); x++) {
2871 if (!strcasecmp(levels[x], name)) {
2886 level = logger_get_dynamic_level(name);
2893 static int logger_unregister_level(
const char *name) {
2896 x = logger_get_dynamic_level(name);
2903 global_logmask &= ~(1 << x);
2904 ast_free(levels[x]);
2914 x = logger_unregister_level(name);
2917 update_logchannels();
2923 ast_debug(1,
"Unregistered dynamic logger level '%s' with index %u.\n", name, x);
2934 logger_queue_limit = queue_limit;
2939 return logger_queue_limit;
2942 static int reload_module(
void)
2944 return reload_logger(0, NULL);
2947 static int unload_module(
void)
2952 static int load_module(
void)
2958 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"Logger",
2959 .support_level = AST_MODULE_SUPPORT_CORE,
2960 .load = load_module,
2961 .unload = unload_module,
2963 .reload = reload_module,
struct ast_variable * next
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
static void logger_print_normal(struct logmsg *logmsg)
Print a normal log message to the channels.
Main Channel structure associated with a channel.
void ast_verb_console_unregister(void)
Unregister this thread's console verbosity level.
struct logformatter formatter
static int init_logger_chain(const char *altconf)
Read config, setup channels.
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_logger_get_dateformat(void)
Get the logger configured date format.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
static ast_mutex_t verb_update_lock
int ast_logger_remove_channel(const char *log_channel)
Delete the specified log channel.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Asterisk backtrace generation.
String manipulation functions.
static const int colors[NUMLOGLEVELS]
Colors used in the console for logging.
Asterisk version information.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define ast_channel_unref(c)
Decrease channel reference count.
int ast_verb_console_get(void)
Get this thread's console verbosity level.
Time-related functions and macros.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
static int force_inline attribute_pure ast_ends_with(const char *str, const char *suffix)
Checks whether a string ends with another.
static void make_filename(const char *channel, char *filename, size_t size)
create the filename that will be used for a logger channel.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
void ast_verb_console_register(int *level)
Register this thread's console verbosity level pointer.
void ast_verb_update(void)
Re-evaluate the system max verbosity level (ast_verb_sys_level).
descriptor for a cli entry.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
int ast_unload_realtime(const char *family)
Release any resources cached for a realtime family.
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Structure for variables, used for configurations and for channel variables.
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
#define ast_json_dump_string(root)
Encode a JSON value to a compact string.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
void ast_verb_console_set(int verb_level)
Set this thread's console verbosity level.
AST_THREADSTORAGE_RAW(in_intercept_routine)
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
static char * custom_dynamic_levels[NUMLOGLEVELS]
Custom dynamic logging levels added by the user.
void ast_log_backtrace(void)
Log a backtrace of the current thread's execution stack to the Asterisk log.
char * term_strip(char *outbuf, const char *inbuf, int maxout)
Remove colorings from a specified string.
int ast_logger_rotate_channel(const char *log_channel)
Rotate the specified log channel.
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
static char * levels[NUMLOGLEVELS]
Logging channels used in the Asterisk logging system.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void logger_queue_start(void)
Start the ast_queue_log() logger.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define ast_strdup(str)
A wrapper for strdup()
int ast_logger_register_level(const char *name)
Register a new logger level.
Definitions to aid in the use of thread local storage.
int ast_syslog_priority_from_loglevel(int level)
Maps an Asterisk log level (i.e. LOG_ERROR) to a syslog priority constant.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
void ast_log_safe(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message with protection against recursion.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
void __ast_verbose_callid(const char *file, int line, const char *func, int level, ast_callid callid, const char *fmt,...)
Send a verbose message (based on verbose level) with deliberately specified callid.
void ast_logger_set_queue_limit(int queue_limit)
Set the maximum number of messages allowed in the processing queue.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
int ast_logger_get_channels(int(*logentry)(const char *channel, const char *type, const char *status, const char *configuration, void *data), void *data)
Retrieve the existing log channels.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
void ast_callid_strnprint(char *buffer, size_t buffer_size, ast_callid callid)
copy a string representation of the callid into a target string
Configuration File Parser.
A structure to hold backtrace information. This structure provides an easy means to store backtrace i...
int ast_store_realtime(const char *family,...) attribute_sentinel
Create realtime configuration.
General Asterisk PBX channel definitions.
Asterisk JSON abstraction layer.
int ast_realtime_require_field(const char *family,...) attribute_sentinel
Inform realtime what fields that may be stored.
Asterisk file paths, configured in asterisk.conf.
int ast_threadstorage_set_ptr(struct ast_threadstorage *ts, void *ptr)
Set a raw pointer from threadstorage.
int ast_get_tid(void)
Get current thread ID.
#define ast_strdupa(s)
duplicate a string in memory from the stack
static char * handle_logger_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to show logging system configuration.
int ast_logger_rotate()
Reload logger while rotating log files.
static int custom_level_still_exists(char **levels, char *level, size_t len)
Checks if level exists in array of level names.
#define ast_dummy_channel_alloc()
Create a fake channel structure.
char * ast_str_append_substr(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Append a non-NULL terminated substring to the end of a dynamic string.
int ast_logger_get_dynamic_level(const char *name)
Retrieve dynamic logging level id.
Data structure associated with a custom dialplan function.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
#define AST_STRING_FIELD(name)
Declare a string field.
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
#define ast_malloc(len)
A wrapper for malloc()
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
void ast_log_callid(int level, const char *file, int line, const char *function, ast_callid callid, const char *fmt,...)
Used for sending a log message with a known call_id This is a modified logger function which is funct...
Syslog support functions for Asterisk logging.
Core PBX routines and definitions.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
int ast_callid_threadassoc_remove(void)
Removes callid from thread storage of the calling thread.
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
int ast_is_logger_initialized(void)
Test if logger is initialized.
Support for dynamic strings.
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
void __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt,...)
Send a verbose message (based on verbose level)
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
ast_trace_indent_type
Controls if and when indenting is applied.
ast_callid ast_create_callid(void)
factory function to create a new uniquely identifying callid.
static struct logchannel * find_logchannel(const char *channel)
Find a particular logger channel by name.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
static void * logger_thread(void *data)
Actual logging thread.
int ast_logger_create_channel(const char *log_channel, const char *components)
Create a log channel.
#define ast_calloc(num, len)
A wrapper for calloc()
Support for logging to various files, console and syslog Configuration in file logger.conf.
Prototypes for public functions only of internal interest,.
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
struct logchannel::@372 list
void * ast_threadstorage_get_ptr(struct ast_threadstorage *ts)
Retrieve a raw pointer from threadstorage.
void * addresses[AST_MAX_BT_FRAMES]
Structure used to handle boolean flags.
void ast_console_toggle_loglevel(int fd, int level, int state)
enables or disables logging of a specified level to the console fd specifies the index of the console...
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
void ast_init_logger_for_socket_console(void)
load logger.conf configuration for console socket connections
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
void ast_console_puts_mutable_full(const char *message, int level, int sublevel)
log the string to the console, and all attached console clients
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
int ast_callid_threadassoc_change(ast_callid callid)
Sets what is stored in the thread storage to the given callid if it does not match what is already th...
Standard Command Line Interface.
static int enabled
Whether or not we are storing history.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int ast_syslog_facility(const char *facility)
Maps a syslog facility name from a string to a syslog facility constant.
static void ast_log_full(int level, int sublevel, const char *file, int line, const char *function, ast_callid callid, const char *fmt, va_list ap)
send log messages to syslog and/or the console
int ast_logger_get_queue_limit(void)
Get the maximum number of messages allowed in the processing queue.
Abstract JSON element (object, array, string, int, ...).
Handy terminal functions for vt* terms.
static char * handle_logger_show_levels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI command to show logging levels.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
String vector definitions.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
void ast_console_puts_mutable(const char *string, int level)
log the string to the console, and all attached console clients
#define ASTERISK_GPL_KEY
The text the key() function should return.
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Asterisk module definitions.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
void ast_callid_threadstorage_auto_clean(ast_callid callid, int callid_created)
Use in conjunction with ast_callid_threadstorage_auto. Cleans up the references and if the callid was...
#define ast_custom_function_register(acf)
Register a custom function.
int ast_callid_threadstorage_auto(ast_callid *callid)
Checks thread storage for a callid and stores a reference if it exists. If not, then a new one will b...
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
void ast_logger_unregister_level(const char *name)
Unregister a previously registered logger level.
#define AST_APP_ARG(name)
Define an application argument.
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.