RTS API Documentation  1.10.11
switch_log.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2021, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  *
28  *
29  * switch_log.c -- Logging
30  *
31  */
32 
33 #include <switch.h>
35 
36 static const char *LEVELS[] = {
37  "DISABLE",
38  "CONSOLE",
39  "ALERT",
40  "CRIT",
41  "ERR",
42  "WARNING",
43  "NOTICE",
44  "INFO",
45  "DEBUG",
46  NULL
47 };
48 
54 };
55 
57 
60 static switch_mutex_t *BINDLOCK = NULL;
61 static switch_queue_t *LOG_QUEUE = NULL;
62 #ifdef SWITCH_LOG_RECYCLE
63 static switch_queue_t *LOG_RECYCLE_QUEUE = NULL;
64 #endif
65 static int8_t THREAD_RUNNING = 0;
66 static uint8_t MAX_LEVEL = 0;
67 static int mods_loaded = 0;
68 static int console_mods_loaded = 0;
70 
71 static int64_t log_sequence = 0;
72 
73 #ifdef WIN32
74 static HANDLE hStdout;
75 static WORD wOldColorAttrs;
76 static CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
77 
78 static WORD
79 #else
80 static const char *
81 #endif
82 
83 
84 
85 
86  COLORS[] =
89 
90 
92 {
93  cJSON *json = NULL;
94  char *hostname;
95  char *full_message = node->content;
96  char *parsed_full_message = NULL;
97  char *field_name = NULL;
98  switch_event_t *log_fields = NULL;
99  switch_core_session_t *session = NULL;
100 
101  if (node->meta && cJSON_IsObject(node->meta)) {
102  if (json_format->custom_field_prefix) {
103  cJSON *field = NULL;
104  json = cJSON_CreateObject();
105  for (field = node->meta->child; field; field = field->next) {
106  if (!zstr(field->string)) {
107  char *field_name = switch_mprintf("%s%s", json_format->custom_field_prefix, field->string);
108  cJSON_AddItemToObject(json, field_name, cJSON_Duplicate(field, cJSON_True));
109  free(field_name);
110  }
111  }
112  } else {
113  json = cJSON_Duplicate(node->meta, cJSON_True);
114  }
115  } else {
116  json = cJSON_CreateObject();
117  }
118 
119  if (json_format->version.name && json_format->version.value) {
120  cJSON_AddItemToObject(json, json_format->version.name, cJSON_CreateString(json_format->version.value));
121  }
122  if (json_format->host.name) {
123  if (json_format->host.value) {
124  cJSON_AddItemToObject(json, json_format->host.name, cJSON_CreateString(json_format->host.value));
125  } else if ((hostname = switch_core_get_variable("hostname")) && !zstr(hostname)) {
126  cJSON_AddItemToObject(json, json_format->host.name, cJSON_CreateString(hostname));
127  } else if ((hostname = switch_core_get_variable("local_ip_v4")) && !zstr(hostname)) {
128  cJSON_AddItemToObject(json, json_format->host.name, cJSON_CreateString(hostname));
129  }
130  }
131  if (json_format->timestamp.name) {
132  double timestamp = node->timestamp;
133  if (json_format->timestamp_divisor > 1.0) {
134  timestamp = timestamp / json_format->timestamp_divisor;
135  }
136  cJSON_AddItemToObject(json, json_format->timestamp.name, cJSON_CreateNumber(timestamp));
137  }
138  if (json_format->level.name) {
139  cJSON_AddItemToObject(json, json_format->level.name, cJSON_CreateNumber(log_level));
140  }
141  if (json_format->ident.name) {
142  if (json_format->ident.value) {
143  cJSON_AddItemToObject(json, json_format->ident.name, cJSON_CreateString(json_format->ident.value));
144  } else {
145  cJSON_AddItemToObject(json, json_format->ident.name, cJSON_CreateString("freeswitch"));
146  }
147  }
148  if (json_format->pid.name) {
149  if (json_format->pid.value) {
150  cJSON_AddItemToObject(json, json_format->pid.name, cJSON_CreateNumber(atoi(json_format->pid.value)));
151  } else {
152  cJSON_AddItemToObject(json, json_format->pid.name, cJSON_CreateNumber((int)getpid()));
153  }
154  }
155  if (json_format->uuid.name && !zstr(node->userdata)) {
156  cJSON_AddItemToObject(json, json_format->uuid.name, cJSON_CreateString(node->userdata));
157  }
158  if (json_format->file.name && !zstr_buf(node->file)) {
159  cJSON_AddItemToObject(json, json_format->file.name, cJSON_CreateString(node->file));
160  if (json_format->line.name) {
161  cJSON_AddItemToObject(json, json_format->line.name, cJSON_CreateNumber(node->line));
162  }
163  }
164  if (json_format->function.name && !zstr_buf(node->func)) {
165  cJSON_AddItemToObject(json, json_format->function.name, cJSON_CreateString(node->func));
166  }
167  if (json_format->sequence.name) {
168  cJSON_AddItemToObject(json, json_format->sequence.name, cJSON_CreateNumber(node->sequence));
169  }
170 
171  /* skip initial space and new line */
172  if (*full_message == ' ') {
173  full_message++;
174  }
175  if (*full_message == '\n') {
176  full_message++;
177  }
178 
179  /* get fields from log tags */
180  if (node->tags) {
181  switch_event_dup(&log_fields, node->tags);
182  }
183 
184  /* get fields from channel data, if configured */
185  if (!zstr(node->userdata) && chan_vars && chan_vars->headers && (session = switch_core_session_locate(node->userdata))) {
188  /* session_fields name mapped to variable name */
189  for (hp = chan_vars->headers; hp; hp = hp->next) {
190  if (!zstr(hp->name) && !zstr(hp->value)) {
191  const char *val = switch_channel_get_variable(channel, hp->value);
192  if (!zstr(val)) {
193  if (!log_fields) {
195  }
197  }
198  }
199  }
201  }
202 
203  /* parse list of fields from message text, if any */
204  if (strncmp(full_message, "LOG_FIELDS", 10) == 0) {
205  switch_event_create_brackets(full_message+10, '[', ']', ',', &log_fields, &parsed_full_message, SWITCH_TRUE);
206  full_message = parsed_full_message;
207  }
208 
209  /* add additional fields */
210  if (log_fields) {
212  const char *prefix = json_format->custom_field_prefix ? json_format->custom_field_prefix : "";
213  for (hp = log_fields->headers; hp; hp = hp->next) {
214  if (!zstr(hp->name) && !zstr(hp->value)) {
215  if (strncmp(hp->name, "@#", 2) == 0) {
216  field_name = switch_mprintf("%s%s", prefix, hp->name + 2);
217  cJSON_AddItemToObject(json, field_name, cJSON_CreateNumber(strtod(hp->value, NULL)));
218  } else {
219  field_name = switch_mprintf("%s%s", prefix, hp->name);
220  cJSON_AddItemToObject(json, field_name, cJSON_CreateString(hp->value));
221  }
222  free(field_name);
223  }
224  }
225  switch_event_destroy(&log_fields);
226  }
227 
228  if (json_format->full_message.name) {
229  cJSON_AddItemToObject(json, json_format->full_message.name, cJSON_CreateString(full_message));
230  } else {
231  cJSON_AddItemToObject(json, "message", cJSON_CreateString(full_message));
232  }
233 
234  if (json_format->short_message.name) {
235  char short_message[151];
236  char *short_message_end = NULL;
237  switch_snprintf(short_message, sizeof(short_message) - 1, "%s", full_message);
238  if ((short_message_end = strchr(short_message, '\n'))) {
239  *short_message_end = '\0';
240  }
241  cJSON_AddItemToObject(json, json_format->short_message.name, cJSON_CreateString(short_message));
242  }
243 
244  switch_safe_free(parsed_full_message);
245 
246  return json;
247 }
248 
250 {
251  switch_log_node_t *node = NULL;
252 #ifdef SWITCH_LOG_RECYCLE
253  void *pop = NULL;
254 
255  if (switch_queue_trypop(LOG_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS) {
256  node = (switch_log_node_t *) pop;
257  } else {
258 #endif
259  node = malloc(sizeof(*node));
260  switch_assert(node);
261 #ifdef SWITCH_LOG_RECYCLE
262  }
263 #endif
264  return node;
265 }
266 
268 {
270 
271  *newnode = *node;
272  newnode->content = NULL;
273 
274  if (node->data) {
275  newnode->data = strdup(node->data);
276  switch_assert(newnode->data);
277 
278  // content is a pointer inside data; need to calculate the new pointer
279  if (node->content && node->content >= node->data) {
280  newnode->content = newnode->data + (node->content - node->data);
281  }
282  }
283 
284  if (node->userdata) {
285  newnode->userdata = strdup(node->userdata);
286  switch_assert(newnode->userdata);
287  }
288 
289  if (node->tags) {
290  switch_event_dup(&newnode->tags, node->tags);
291  }
292 
293  if (node->meta) {
294  newnode->meta = cJSON_Duplicate(node->meta, cJSON_True);
295  }
296 
297  return newnode;
298 }
299 
301 {
302  switch_log_node_t *node;
303 
304  if (!pnode) {
305  return;
306  }
307 
308  node = *pnode;
309 
310  if (node) {
311  switch_safe_free(node->userdata);
312  switch_safe_free(node->data);
313  if (node->tags) {
314  switch_event_destroy(&node->tags);
315  }
316  if (node->meta) {
317  cJSON_Delete(node->meta);
318  node->meta = NULL;
319  }
320 #ifdef SWITCH_LOG_RECYCLE
321  if (switch_queue_trypush(LOG_RECYCLE_QUEUE, node) != SWITCH_STATUS_SUCCESS) {
322  free(node);
323  }
324 #else
325  free(node);
326 #endif
327  }
328  *pnode = NULL;
329 }
330 
332 {
333  if (level > SWITCH_LOG_DEBUG) {
334  level = SWITCH_LOG_DEBUG;
335  }
336  return LEVELS[level + 1];
337 }
338 
340 {
341  switch (level) {
342  case SWITCH_LOG_DEBUG:
343  return (1<<7);
344  case SWITCH_LOG_INFO:
345  return (1<<6);
346  case SWITCH_LOG_NOTICE:
347  return (1<<5);
348  case SWITCH_LOG_WARNING:
349  return (1<<4);
350  case SWITCH_LOG_ERROR:
351  return (1<<3);
352  case SWITCH_LOG_CRIT:
353  return (1<<2);
354  case SWITCH_LOG_ALERT:
355  return (1<<1);
356  case SWITCH_LOG_CONSOLE:
357  return (1<<0);
358  default:
359  return 0;
360  }
361 }
362 
363 SWITCH_DECLARE(uint32_t) switch_log_str2mask(const char *str)
364 {
365  int argc = 0, x = 0;
366  char *argv[10] = { 0 };
367  uint32_t mask = 0;
368  char *p = strdup(str);
370 
371  switch_assert(p);
372 
373  if ((argc = switch_separate_string(p, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
374  for (x = 0; x < argc && argv[x]; x++) {
375  if (!strcasecmp(argv[x], "all")) {
376  mask = 0xFF;
377  break;
378  } else {
379  level = switch_log_str2level(argv[x]);
380 
381  if (level != SWITCH_LOG_INVALID) {
382  mask |= switch_log_to_mask(level);
383  }
384  }
385  }
386  }
387 
388  free(p);
389 
390  return mask;
391 }
392 
394 {
395  int x = 0;
397 
398  if (switch_is_number(str)) {
399  x = atoi(str);
400 
401  if (x > SWITCH_LOG_INVALID) {
402  return SWITCH_LOG_INVALID - 1;
403  } else if (x < 0) {
404  return 0;
405  } else {
406  return x;
407  }
408  }
409 
410 
411  for (x = 0;; x++) {
412  if (!LEVELS[x]) {
413  break;
414  }
415 
416  if (!strcasecmp(LEVELS[x], str)) {
417  level = (switch_log_level_t)(x - 1);
418  break;
419  }
420  }
421 
422  return level;
423 }
424 
426 {
427  switch_log_binding_t *ptr = NULL, *last = NULL;
429 
431  for (ptr = BINDINGS; ptr; ptr = ptr->next) {
432  if (ptr->function == function) {
433  if (last) {
434  last->next = ptr->next;
435  } else {
436  BINDINGS = ptr->next;
437  }
438  status = SWITCH_STATUS_SUCCESS;
439  mods_loaded--;
440  if (ptr->is_console) {
442  }
443  break;
444  }
445  last = ptr;
446  }
448 
449  return status;
450 }
451 
453 {
454  switch_log_binding_t *binding = NULL, *ptr = NULL;
455  switch_assert(function != NULL);
456 
457  if (!(binding = switch_core_alloc(LOG_POOL, sizeof(*binding)))) {
458  return SWITCH_STATUS_MEMERR;
459  }
460 
461  if ((uint8_t) level > MAX_LEVEL) {
462  MAX_LEVEL = level;
463  }
464 
465  binding->function = function;
466  binding->level = level;
467  binding->is_console = is_console;
468 
470  for (ptr = BINDINGS; ptr && ptr->next; ptr = ptr->next);
471 
472  if (ptr) {
473  ptr->next = binding;
474  } else {
475  BINDINGS = binding;
476  }
477  if (is_console) {
479  }
480  mods_loaded++;
482 
483  return SWITCH_STATUS_SUCCESS;
484 }
485 
487 
488 static void *SWITCH_THREAD_FUNC log_thread(switch_thread_t *t, void *obj)
489 {
490 
491  if (!obj) {
492  obj = NULL;
493  }
494  THREAD_RUNNING = 1;
495 
496  while (THREAD_RUNNING == 1) {
497  void *pop = NULL;
498  switch_log_node_t *node = NULL;
499  switch_log_binding_t *binding;
500 
501  if (switch_queue_pop(LOG_QUEUE, &pop) != SWITCH_STATUS_SUCCESS) {
502  break;
503  }
504 
505  if (!pop) {
506  THREAD_RUNNING = -1;
507  break;
508  }
509 
510  node = (switch_log_node_t *) pop;
512  node->sequence = ++log_sequence;
513  for (binding = BINDINGS; binding; binding = binding->next) {
514  if (binding->level >= node->level) {
515  binding->function(node, node->level);
516  }
517  }
519 
520  switch_log_node_free(&node);
521 
522  }
523 
524  THREAD_RUNNING = 0;
526  return NULL;
527 }
528 
529 SWITCH_DECLARE(void) switch_log_meta_printf(switch_text_channel_t channel, const char *file, const char *func, int line,
530  const char *userdata, switch_log_level_t level, cJSON **meta, const char *fmt, ...)
531 {
532  va_list ap;
533  va_start(ap, fmt);
534  switch_log_meta_vprintf(channel, file, func, line, userdata, level, meta, fmt, ap);
535  va_end(ap);
536 }
537 
538 SWITCH_DECLARE(void) switch_log_printf(switch_text_channel_t channel, const char *file, const char *func, int line,
539  const char *userdata, switch_log_level_t level, const char *fmt, ...)
540 {
541  va_list ap;
542 
543  va_start(ap, fmt);
544  switch_log_meta_vprintf(channel, file, func, line, userdata, level, NULL, fmt, ap);
545  va_end(ap);
546 }
547 
548 #define do_mods (LOG_QUEUE && THREAD_RUNNING)
549 SWITCH_DECLARE(void) switch_log_vprintf(switch_text_channel_t channel, const char *file, const char *func, int line,
550  const char *userdata, switch_log_level_t level, const char *fmt, va_list ap)
551 {
552  switch_log_meta_vprintf(channel, file, func, line, userdata, level, NULL, fmt, ap);
553 }
554 SWITCH_DECLARE(void) switch_log_meta_vprintf(switch_text_channel_t channel, const char *file, const char *func, int line,
555  const char *userdata, switch_log_level_t level, cJSON **meta, const char *fmt, va_list ap)
556 {
557  cJSON *log_meta = NULL;
558  char *data = NULL;
559  char *new_fmt = NULL;
560  int ret = 0;
561  FILE *handle;
562  const char *filep = (file ? switch_cut_path(file) : "");
563  const char *funcp = (func ? func : "");
564  char *content = NULL;
566  uint32_t len;
567 #ifdef SWITCH_FUNC_IN_LOG
568  const char *extra_fmt = "%s [%s] %s:%d %s()%c%s";
569 #else
570  const char *extra_fmt = "%s [%s] %s:%d%c%s";
571 #endif
573  switch_log_level_t special_level = SWITCH_LOG_UNINIT;
574 
575  if (meta && *meta) {
576  log_meta = *meta;
577  *meta = NULL;
578  }
579 
580  if (limit_level == SWITCH_LOG_DISABLE) {
581  goto end;
582  }
583 
584  if (channel == SWITCH_CHANNEL_ID_SESSION && userdata) {
585  switch_core_session_t *session = (switch_core_session_t *) userdata;
586  special_level = session->loglevel;
587  if (limit_level < session->loglevel) {
588  limit_level = session->loglevel;
589  }
590  }
591 
592  if (level > 100) {
593  if ((uint32_t) (level - 100) > runtime.debug_level) {
594  goto end;
595  }
596 
597  level = 1;
598  }
599 
600  if (level > limit_level) {
601  goto end;
602  }
603 
605 
606  handle = switch_core_data_channel(channel);
607 
608  if (channel != SWITCH_CHANNEL_ID_LOG_CLEAN) {
609  char date[80] = "";
610  //switch_size_t retsize;
612 
613  switch_time_exp_lt(&tm, now);
614  switch_snprintf(date, sizeof(date), "%0.4d-%0.2d-%0.2d %0.2d:%0.2d:%0.2d.%0.6d %0.2f%%%%",
615  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, switch_core_idle_cpu());
616 
617  //switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
618 
619 #ifdef SWITCH_FUNC_IN_LOG
620  len = (uint32_t) (strlen(extra_fmt) + strlen(date) + strlen(filep) + 32 + strlen(funcp) + strlen(fmt));
621 #else
622  len = (uint32_t) (strlen(extra_fmt) + strlen(date) + strlen(filep) + 32 + strlen(fmt));
623 #endif
624  new_fmt = malloc(len + 1);
625  switch_assert(new_fmt);
626 #ifdef SWITCH_FUNC_IN_LOG
627  switch_snprintf(new_fmt, len, extra_fmt, date, switch_log_level2str(level), filep, line, funcp, 128, fmt);
628 #else
629  switch_snprintf(new_fmt, len, extra_fmt, date, switch_log_level2str(level), filep, line, 128, fmt);
630 #endif
631 
632  fmt = new_fmt;
633  }
634 
635  ret = switch_vasprintf(&data, fmt, ap);
636 
637  if (ret == -1) {
638  fprintf(stderr, "Memory Error\n");
639  goto end;
640  }
641 
642  if (channel == SWITCH_CHANNEL_ID_LOG_CLEAN) {
643  content = data;
644  } else {
645  if ((content = strchr(data, 128))) {
646  *content = ' ';
647  }
648  }
649 
650  if (channel == SWITCH_CHANNEL_ID_EVENT) {
651  switch_event_t *event;
653  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-Data", data);
654  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-File", filep);
655  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Log-Function", funcp);
656  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Log-Line", "%d", line);
657  switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Log-Level", "%d", (int) level);
658  if (!zstr(userdata)) {
659  switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "User-Data", userdata);
660  }
661  switch_event_fire(&event);
662  data = NULL;
663  }
664 
665  goto end;
666  }
667 
668  if (console_mods_loaded == 0 || !do_mods) {
669  if (handle) {
670  int aok = 1;
671 #ifndef WIN32
672 
673  fd_set can_write;
674  int fd;
675  struct timeval to;
676 
677  fd = fileno(handle);
678  memset(&to, 0, sizeof(to));
679  FD_ZERO(&can_write);
680  FD_SET(fd, &can_write);
681  to.tv_sec = 0;
682  to.tv_usec = 100000;
683  if (select(fd + 1, NULL, &can_write, NULL, &to) > 0) {
684  aok = FD_ISSET(fd, &can_write);
685  } else {
686  aok = 0;
687  }
688 #endif
689  if (aok) {
690  if (COLORIZE) {
691 
692 #ifdef WIN32
693  SetConsoleTextAttribute(hStdout, COLORS[level]);
694  WriteFile(hStdout, data, (DWORD) strlen(data), NULL, NULL);
695  SetConsoleTextAttribute(hStdout, wOldColorAttrs);
696 #else
697  fprintf(handle, "%s%s%s", COLORS[level], data, SWITCH_SEQ_DEFAULT_COLOR);
698 #endif
699  } else {
700  fprintf(handle, "%s", data);
701  }
702  }
703  }
704  }
705 
706  if (do_mods && level <= MAX_LEVEL) {
708 
709  node->data = data;
710  data = NULL;
711  switch_set_string(node->file, filep);
712  switch_set_string(node->func, funcp);
713  node->line = line;
714  node->level = level;
715  node->slevel = special_level;
716  node->content = content;
717  node->timestamp = now;
718  node->channel = channel;
719  node->tags = NULL;
720  node->meta = log_meta;
721  log_meta = NULL;
722  if (channel == SWITCH_CHANNEL_ID_SESSION) {
723  switch_core_session_t *session = (switch_core_session_t *) userdata;
724  node->userdata = userdata ? strdup(switch_core_session_get_uuid(session)) : NULL;
725  if (session) {
727  }
728  } else {
729  node->userdata = !zstr(userdata) ? strdup(userdata) : NULL;
730  }
731 
732  if (switch_queue_trypush(LOG_QUEUE, node) != SWITCH_STATUS_SUCCESS) {
733  switch_log_node_free(&node);
734  }
735  }
736 
737  end:
738 
739  cJSON_Delete(log_meta);
740  switch_safe_free(data);
741  switch_safe_free(new_fmt);
742 
743 }
744 
746 {
747  switch_threadattr_t *thd_attr;;
748 
749  switch_assert(pool != NULL);
750 
751  LOG_POOL = pool;
752 
754 
756 #ifdef SWITCH_LOG_RECYCLE
757  switch_queue_create(&LOG_RECYCLE_QUEUE, SWITCH_CORE_QUEUE_LEN, LOG_POOL);
758 #endif
761  switch_thread_create(&thread, thd_attr, log_thread, NULL, LOG_POOL);
762 
763  while (!THREAD_RUNNING) {
765  }
766 
767  if (colorize) {
768 #ifdef WIN32
769  hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
770  if (switch_core_get_console() == stdout && hStdout != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) {
771  wOldColorAttrs = csbiInfo.wAttributes;
773  }
774 #else
776 #endif
777  }
778 
779 
780  return SWITCH_STATUS_SUCCESS;
781 }
782 
784 {
785 #ifdef SWITCH_LOG_RECYCLE
786  void *pop;
787  int size = switch_queue_size(LOG_RECYCLE_QUEUE);
788  switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CONSOLE, "Returning %d recycled log node(s) %d bytes\n", size,
789  (int) sizeof(switch_log_node_t) * size);
790  while (switch_queue_trypop(LOG_RECYCLE_QUEUE, &pop) == SWITCH_STATUS_SUCCESS) {
791  switch_log_node_free(&pop);
792  }
793 #else
794  return;
795 #endif
796 
797 }
798 
800 {
801  switch_status_t st;
802 
803 
804  switch_queue_push(LOG_QUEUE, NULL);
805  while (THREAD_RUNNING) {
807  }
808 
810 
812 
813  return SWITCH_STATUS_SUCCESS;
814 }
815 
816 
817 /* For Emacs:
818  * Local Variables:
819  * mode:c
820  * indent-tabs-mode:t
821  * tab-width:4
822  * c-basic-offset:4
823  * End:
824  * For VIM:
825  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
826  */
switch_log_json_format_item_t sequence
Definition: switch_log.h:101
switch_time_t switch_micro_time_now(void)
Get the current epoch time in microseconds.
Definition: switch_time.c:311
#define switch_event_fire(event)
Fire an event filling in most of the arguements with obvious values.
Definition: switch_event.h:413
unsigned int switch_queue_size(switch_queue_t *queue)
Definition: switch_apr.c:1238
switch_xml_t switch_status_t switch_event_running(void)
Determine if the event system has been initialized.
Definition: switch_event.c:425
#define SWITCH_CHANNEL_SESSION_LOG(x)
void switch_core_memory_reclaim_logger(void)
Definition: switch_log.c:783
static int console_mods_loaded
Definition: switch_log.c:68
#define SWITCH_THREAD_FUNC
switch_text_channel_t
A target to write log/debug info to.
Log Data.
Definition: switch_log.h:49
static uint8_t MAX_LEVEL
Definition: switch_log.c:66
#define SWITCH_CHANNEL_LOG
switch_log_json_format_item_t version
Definition: switch_log.h:87
switch_event_t * tags
Definition: switch_log.h:68
#define do_mods
Definition: switch_log.c:548
switch_log_function_t function
Definition: switch_log.c:50
static switch_memory_pool_t * LOG_POOL
Definition: switch_log.c:58
switch_bool_t
Definition: switch_types.h:437
switch_status_t switch_event_create_brackets(char *data, char a, char b, char c, switch_event_t **event, char **new_data, switch_bool_t dup)
#define SWITCH_SEQ_FMAGEN
Definition: switch_types.h:97
switch_log_node_t * switch_log_node_dup(const switch_log_node_t *node)
Definition: switch_log.c:267
switch_status_t switch_threadattr_stacksize_set(switch_threadattr_t *attr, switch_size_t stacksize)
Definition: switch_apr.c:683
void switch_log_meta_printf(switch_text_channel_t channel, const char *file, const char *func, int line, const char *userdata, switch_log_level_t level, cJSON **meta, const char *fmt,...)
Definition: switch_log.c:529
switch_memory_pool_t * pool
switch_status_t switch_event_add_header(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *fmt,...) PRINTF_FUNCTION(4
Add a header to an event.
Representation of an event.
Definition: switch_event.h:80
switch_status_t switch_log_unbind_logger(switch_log_function_t function)
Definition: switch_log.c:425
static int64_t log_sequence
Definition: switch_log.c:71
switch_log_json_format_item_t pid
Definition: switch_log.h:92
An event Header.
Definition: switch_event.h:65
switch_status_t switch_queue_trypop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1264
struct switch_log_binding * next
Definition: switch_log.c:53
switch_bool_t switch_is_number(const char *str)
switch_status_t switch_time_exp_lt(switch_time_exp_t *result, switch_time_t input)
Definition: switch_apr.c:346
switch_log_json_format_item_t timestamp
Definition: switch_log.h:89
void switch_log_printf(switch_text_channel_t channel, const char *file, const char *func, int line, const char *userdata, switch_log_level_t level, const char *fmt,...)
Definition: switch_log.c:538
switch_status_t switch_queue_pop(switch_queue_t *queue, void **data)
Definition: switch_apr.c:1243
static int mods_loaded
Definition: switch_log.c:67
switch_status_t switch_event_dup(switch_event_t **event, switch_event_t *todup)
Duplicate an event.
static switch_thread_t * thread
Definition: switch_log.c:486
int switch_snprintf(_Out_z_cap_(len) char *buf, _In_ switch_size_t len, _In_z_ _Printf_format_string_ const char *format,...)
struct switch_runtime runtime
Definition: switch_core.c:86
static switch_log_binding_t * BINDINGS
Definition: switch_log.c:59
#define zstr(x)
Definition: switch_utils.h:314
int cJSON_bool fmt
Definition: switch_cJSON.h:150
switch_log_json_format_item_t ident
Definition: switch_log.h:91
#define SWITCH_SEQ_FYELLOW
Definition: switch_types.h:95
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:313
_Ret_ switch_channel_t * switch_core_session_get_channel(_In_ switch_core_session_t *session)
Retrieve a pointer to the channel object associated with a given session.
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
switch_log_json_format_item_t line
Definition: switch_log.h:95
void switch_log_meta_vprintf(switch_text_channel_t channel, const char *file, const char *func, int line, const char *userdata, switch_log_level_t level, cJSON **meta, const char *fmt, va_list ap)
Definition: switch_log.c:554
uint32_t switch_log_str2mask(const char *str)
Definition: switch_log.c:363
int64_t switch_time_t
Definition: switch_apr.h:188
double switch_core_idle_cpu(void)
unsigned int switch_separate_string(_In_ char *buf, char delim, _Post_count_(return) char **array, unsigned int arraylen)
Separate a string into an array based on a character delimiter.
struct cJSON * child
Definition: switch_cJSON.h:101
static void *SWITCH_THREAD_FUNC log_thread(switch_thread_t *t, void *obj)
Definition: switch_log.c:488
char * string
Definition: switch_cJSON.h:114
#define SWITCH_CORE_QUEUE_LEN
Definition: switch_types.h:593
static int switch_log_to_mask(switch_log_level_t level)
Definition: switch_log.c:339
static switch_queue_t * LOG_QUEUE
Definition: switch_log.c:61
#define cJSON_True
Definition: switch_cJSON.h:83
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:308
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:684
#define switch_channel_get_variable(_c, _v)
#define SWITCH_THREAD_STACKSIZE
Definition: switch_types.h:584
static int8_t THREAD_RUNNING
Definition: switch_log.c:65
switch_status_t switch_event_add_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data)
Add a string header to an event.
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:885
switch_log_json_format_item_t uuid
Definition: switch_log.h:93
#define SWITCH_SEQ_FCYAN
Definition: switch_types.h:98
switch_log_level_t slevel
Definition: switch_log.h:67
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:293
struct cJSON * next
Definition: switch_cJSON.h:98
switch_status_t switch_thread_join(switch_status_t *retval, switch_thread_t *thd)
Definition: switch_apr.c:1379
switch_status_t(* switch_log_function_t)(const switch_log_node_t *node, switch_log_level_t level)
Definition: switch_log.h:104
switch_log_json_format_item_t full_message
Definition: switch_log.h:97
int switch_vasprintf(_Out_opt_ char **buf, _In_z_ _Printf_format_string_ const char *format, _In_ va_list ap)
FILE * switch_core_data_channel(switch_text_channel_t channel)
Retrieve a FILE stream of a given text channel name.
Definition: switch_core.c:286
static const char * LEVELS[]
Definition: switch_log.c:36
#define SWITCH_SEQ_FRED
Definition: switch_types.h:93
static const char * COLORS[]
Definition: switch_log.c:86
void switch_cond_next(void)
Definition: switch_time.c:658
#define zstr_buf(s)
Definition: switch_utils.h:318
char * switch_core_get_variable(_In_z_ const char *varname)
Retrieve a global variable from the core.
static switch_bool_t COLORIZE
Definition: switch_log.c:69
static switch_status_t switch_event_create_plain(switch_event_t **event, switch_event_types_t event_id)
Definition: switch_event.h:386
const char * switch_log_level2str(switch_log_level_t level)
Definition: switch_log.c:331
switch_time_t timestamp
Definition: switch_log.h:61
void switch_core_session_rwunlock(_In_ switch_core_session_t *session)
Unlock a read or write lock on as given session.
char * switch_core_session_get_uuid(_In_ switch_core_session_t *session)
Retrieve the unique identifier from a session.
switch_log_level_t switch_log_str2level(const char *str)
Definition: switch_log.c:393
switch_status_t switch_log_shutdown(void)
Shut down the logging engine.
Definition: switch_log.c:799
static switch_mutex_t * BINDLOCK
Definition: switch_log.c:60
struct fspr_thread_mutex_t switch_mutex_t
Definition: switch_apr.h:314
switch_log_json_format_item_t short_message
Definition: switch_log.h:98
static switch_log_node_t * switch_log_node_alloc(void)
Definition: switch_log.c:249
switch_status_t switch_log_bind_logger(switch_log_function_t function, switch_log_level_t level, switch_bool_t is_console)
Definition: switch_log.c:452
int64_t sequence
Definition: switch_log.h:70
switch_status_t
Common return values.
struct switch_event_header * next
Definition: switch_event.h:76
cJSON * switch_log_node_to_json(const switch_log_node_t *node, int log_level, switch_log_json_format_t *json_format, switch_event_t *chan_vars)
Convert a log node to JSON object. Destroy JSON object when finished.
Definition: switch_log.c:91
#define switch_core_session_locate(uuid_str)
Locate a session based on it&#39;s uuid.
Definition: switch_core.h:932
switch_log_level_t hard_log_level
const char * custom_field_prefix
Definition: switch_log.h:99
Main Library Header.
#define SWITCH_SEQ_DEFAULT_COLOR
Definition: switch_types.h:70
#define switch_event_create(event, id)
Create a new event assuming it will not be custom event and therefore hiding the unused parameters...
Definition: switch_event.h:384
switch_log_json_format_item_t level
Definition: switch_log.h:90
#define SWITCH_DECLARE(type)
void switch_log_vprintf(switch_text_channel_t channel, const char *file, const char *func, int line, const char *userdata, switch_log_level_t level, const char *fmt, va_list ap)
Definition: switch_log.c:549
#define SWITCH_SEQ_FGREEN
Definition: switch_types.h:94
#define switch_set_string(_dst, _src)
Definition: switch_utils.h:734
switch_status_t switch_queue_trypush(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1279
void switch_log_node_free(switch_log_node_t **pnode)
Definition: switch_log.c:300
switch_status_t switch_queue_push(switch_queue_t *queue, void *data)
Definition: switch_apr.c:1253
switch_status_t switch_log_init(switch_memory_pool_t *pool, switch_bool_t colorize)
Definition: switch_log.c:745
switch_log_json_format_item_t host
Definition: switch_log.h:88
switch_status_t switch_threadattr_create(switch_threadattr_t **new_attr, switch_memory_pool_t *pool)
Definition: switch_apr.c:665
switch_status_t switch_thread_create(switch_thread_t **new_thread, switch_threadattr_t *attr, switch_thread_start_t func, void *data, switch_memory_pool_t *cont)
Definition: switch_apr.c:698
uint32_t debug_level
switch_log_json_format_item_t function
Definition: switch_log.h:96
FILE * switch_core_get_console(void)
Get the output console.
Definition: switch_core.c:253
struct fspr_pool_t switch_memory_pool_t
switch_status_t switch_queue_create(switch_queue_t **queue, unsigned int queue_capacity, switch_memory_pool_t *pool)
Definition: switch_apr.c:1233
switch_log_level_t loglevel
void switch_event_destroy(switch_event_t **event)
Destroy an event.
switch_text_channel_t channel
Definition: switch_log.h:66
switch_status_t switch_channel_get_log_tags(switch_channel_t *channel, switch_event_t **log_tags)
switch_log_level_t level
Definition: switch_log.c:51
#define switch_assert(expr)
struct fspr_thread_t switch_thread_t
Definition: switch_apr.h:941
const char * switch_cut_path(const char *in)
Create a pointer to the file name in a given file path eliminating the directory name.
JSON Log formatting data.
Definition: switch_log.h:86
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
memset(buf, 0, buflen)
switch_log_json_format_item_t file
Definition: switch_log.h:94
switch_log_level_t
Log Level Enumeration.
switch_log_level_t level
Definition: switch_log.h:59
switch_event_header_t * headers
Definition: switch_event.h:90