2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
22 * \brief Support for logging to various files, console and syslog
23 * Configuration in file logger.conf
26 #ifndef _ASTERISK_LOGGER_H
27 #define _ASTERISK_LOGGER_H
29 #include "asterisk/options.h" /* need option_debug */
31 #if defined(__cplusplus) || defined(c_plusplus)
35 #define EVENTLOG "event_log"
36 #define QUEUELOG "queue_log"
38 #define DEBUG_M(a) { \
42 #define _A_ __FILE__, __LINE__, __FUNCTION__
44 #define VERBOSE_PREFIX_1 " "
45 #define VERBOSE_PREFIX_2 " == "
46 #define VERBOSE_PREFIX_3 " -- "
47 #define VERBOSE_PREFIX_4 " > "
49 #define AST_CALLID_BUFFER_LENGTH 13
51 enum ast_logger_results {
52 AST_LOGGER_SUCCESS = 0, /*!< Log channel was created or deleted successfully*/
53 AST_LOGGER_FAILURE = 1, /*!< Log channel already exists for create or doesn't exist for deletion of log channel */
54 AST_LOGGER_DECLINE = -1, /*!< Log channel request was not accepted */
55 AST_LOGGER_ALLOC_ERROR = -2 /*!< filename allocation error */
58 /*! \brief Used for sending a log message
59 This is the standard logger function. Probably the only way you will invoke it would be something like this:
60 ast_log(AST_LOG_WHATEVER, "Problem with the %s Captain. We should get some more. Will %d be enough?\n", "flux capacitor", 10);
61 where WHATEVER is one of ERROR, DEBUG, EVENT, NOTICE, or WARNING depending
62 on which log you wish to output to. These are implemented as macros, that
63 will provide the function with the needed arguments.
65 \param level Type of log event
66 \param file Will be provided by the AST_LOG_* macro
67 \param line Will be provided by the AST_LOG_* macro
68 \param function Will be provided by the AST_LOG_* macro
69 \param fmt This is what is important. The format is the same as your favorite breed of printf. You know how that works, right? :-)
72 void ast_log(int level, const char *file, int line, const char *function, const char *fmt, ...)
73 __attribute__((format(printf, 5, 6)));
75 void ast_log_ap(int level, const char *file, int line, const char *function, const char *fmt, va_list ap)
76 __attribute__((format(printf, 5, 0)));
79 * \brief Used for sending a log message with protection against recursion.
81 * \note This function should be used by all error messages that might be directly
82 * or indirectly caused by logging.
84 * \see ast_log for documentation on the parameters.
86 void ast_log_safe(int level, const char *file, int line, const char *function, const char *fmt, ...)
87 __attribute__((format(printf, 5, 6)));
89 /* XXX needs documentation */
90 typedef unsigned int ast_callid;
92 /*! \brief Used for sending a log message with a known call_id
93 This is a modified logger function which is functionally identical to the above logger function,
94 it just include a call_id argument as well. If NULL is specified here, no attempt will be made to
95 join the log message with a call_id.
97 \param level Type of log event
98 \param file Will be provided by the AST_LOG_* macro
99 \param line Will be provided by the AST_LOG_* macro
100 \param function Will be provided by the AST_LOG_* macro
101 \param callid This is the ast_callid that is associated with the log message. May be NULL.
102 \param fmt This is what is important. The format is the same as your favorite breed of printf. You know how that works, right? :-)
104 void ast_log_callid(int level, const char *file, int line, const char *function, ast_callid callid, const char *fmt, ...)
105 __attribute__((format(printf, 6, 7)));
108 * \brief Retrieve the existing log channels
109 * \param logentry A callback to an updater function
110 * \param data Data passed into the callback for manipulation
112 * For each of the logging channels, logentry will be executed with the
113 * channel file name, log type, status of the log, and configuration levels.
115 * \retval 0 on success
116 * \retval 1 on failure
117 * \retval -2 on allocation error
119 int ast_logger_get_channels(int (*logentry)(const char *channel, const char *type,
120 const char *status, const char *configuration, void *data), void *data);
123 * \brief Create a log channel
125 * \param log_channel Log channel to create
126 * \param components Logging config levels to add to the log channel
128 int ast_logger_create_channel(const char *log_channel, const char *components);
131 * \brief Delete the specified log channel
133 * \param log_channel The log channel to delete
135 int ast_logger_remove_channel(const char *log_channel);
138 * \brief Log a backtrace of the current thread's execution stack to the Asterisk log
140 void ast_log_backtrace(void);
142 /*! \brief Reload logger while rotating log files */
143 int ast_logger_rotate(void);
146 * \brief Rotate the specified log channel.
148 * \param log_channel The log channel to rotate
150 int ast_logger_rotate_channel(const char *log_channel);
152 void __attribute__((format(printf, 5, 6))) ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt, ...);
155 * \brief Send a verbose message (based on verbose level)
157 * \details This works like ast_log, but prints verbose messages to the console depending on verbosity level set.
159 * ast_verbose(VERBOSE_PREFIX_3 "Whatever %s is happening\n", "nothing");
161 * This will print the message to the console if the verbose level is set to a level >= 3
163 * Note the absence of a comma after the VERBOSE_PREFIX_3. This is important.
164 * VERBOSE_PREFIX_1 through VERBOSE_PREFIX_4 are defined.
166 * \version 11 added level parameter
168 void __attribute__((format(printf, 5, 6))) __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...);
171 * \brief Send a verbose message (based on verbose level) with deliberately specified callid
173 * \details just like __ast_verbose, only __ast_verbose_callid allows you to specify which callid is being used
174 * for the log without needing to bind it to a thread. NULL is a valid argument for this function and will
175 * allow you to specify that a log will never display a call id even when there is a call id bound to the
178 void __attribute__((format(printf, 6, 7))) __ast_verbose_callid(const char *file, int line, const char *func, int level, ast_callid callid, const char *fmt, ...);
180 #define ast_verbose(...) __ast_verbose(_A_, -1, __VA_ARGS__)
181 #define ast_verbose_callid(callid, ...) __ast_verbose_callid(_A_, -1, callid, __VA_ARGS__)
183 void __attribute__((format(printf, 6, 0))) __ast_verbose_ap(const char *file, int line, const char *func, int level, ast_callid callid, const char *fmt, va_list ap);
185 void __attribute__((format(printf, 2, 3))) ast_child_verbose(int level, const char *fmt, ...);
187 int ast_register_verbose(void (*verboser)(const char *string)) attribute_warn_unused_result;
188 int ast_unregister_verbose(void (*verboser)(const char *string)) attribute_warn_unused_result;
191 * These gymnastics are due to platforms which designate char as unsigned by
192 * default. Level is the negative character -- offset by 1, because \0 is
193 * the string terminator.
195 #define VERBOSE_MAGIC2LEVEL(x) (((char) -*(signed char *) (x)) - 1)
196 #define VERBOSE_HASMAGIC(x) (*(signed char *) (x) < 0)
198 void ast_console_puts(const char *string);
201 * \brief log the string to the console, and all attached console clients
203 * \param string The message to write to the console
204 * \param level The log level of the message
206 * \version 1.6.1 added level parameter
208 void ast_console_puts_mutable(const char *string, int level);
211 * \brief log the string to the console, and all attached console clients
214 * \param message The message to write to the console
215 * \param sublevel If the log level supports it, the sub-level of the message
216 * \param level The log level of the message
218 void ast_console_puts_mutable_full(const char *message, int level, int sublevel);
220 void ast_console_toggle_mute(int fd, int silent);
223 * \brief enables or disables logging of a specified level to the console
224 * fd specifies the index of the console receiving the level change
225 * level specifies the index of the logging level being toggled
226 * state indicates whether logging will be on or off (0 for off, 1 for on)
228 void ast_console_toggle_loglevel(int fd, int level, int state);
230 /* Note: The AST_LOG_* macros below are the same as
231 * the LOG_* macros and are intended to eventually replace
232 * the LOG_* macros to avoid name collisions with the syslog(3)
233 * log levels. However, please do NOT remove
234 * the LOG_* macros from the source since these may be still
235 * needed for third-party modules
241 #define __LOG_DEBUG 0
242 #define LOG_DEBUG __LOG_DEBUG, _A_
247 #define AST_LOG_DEBUG __LOG_DEBUG, _A_
252 #define __LOG_TRACE 1
253 #define LOG_TRACE __LOG_TRACE, _A_
258 #define AST_LOG_TRACE __LOG_TRACE, _A_
263 #define __LOG_NOTICE 2
264 #define LOG_NOTICE __LOG_NOTICE, _A_
266 #ifdef AST_LOG_NOTICE
267 #undef AST_LOG_NOTICE
269 #define AST_LOG_NOTICE __LOG_NOTICE, _A_
274 #define __LOG_WARNING 3
275 #define LOG_WARNING __LOG_WARNING, _A_
277 #ifdef AST_LOG_WARNING
278 #undef AST_LOG_WARNING
280 #define AST_LOG_WARNING __LOG_WARNING, _A_
285 #define __LOG_ERROR 4
286 #define LOG_ERROR __LOG_ERROR, _A_
291 #define AST_LOG_ERROR __LOG_ERROR, _A_
296 #define __LOG_VERBOSE 5
297 #define LOG_VERBOSE __LOG_VERBOSE, _A_
299 #ifdef AST_LOG_VERBOSE
300 #undef AST_LOG_VERBOSE
302 #define AST_LOG_VERBOSE __LOG_VERBOSE, _A_
308 #define LOG_DTMF __LOG_DTMF, _A_
313 #define AST_LOG_DTMF __LOG_DTMF, _A_
315 #define NUMLOGLEVELS 32
318 * \brief Get the debug level for a module
319 * \param module the name of module
320 * \return the debug level
322 unsigned int ast_debug_get_by_module(const char *module);
325 * \brief Register a new logger level
326 * \param name The name of the level to be registered
327 * \retval -1 if an error occurs
328 * \retval non-zero level to be used with ast_log for sending messages to this level
331 int ast_logger_register_level(const char *name);
334 * \brief Retrieve dynamic logging level id
335 * \param name The name of the level
336 * \return The unique integer id for the given level
337 * \retval -1 if level name not found
339 int ast_logger_get_dynamic_level(const char *name);
342 * \brief Unregister a previously registered logger level
343 * \param name The name of the level to be unregistered
346 void ast_logger_unregister_level(const char *name);
349 * \brief Get the logger configured date format
351 * \return The date format string
355 const char *ast_logger_get_dateformat(void);
358 * \brief factory function to create a new uniquely identifying callid.
360 * \return The call id
362 ast_callid ast_create_callid(void);
365 * \brief extracts the callerid from the thread
367 * \retval Non-zero Call id related to the thread
368 * \retval 0 if no call_id is present in the thread
370 ast_callid ast_read_threadstorage_callid(void);
373 * \brief Sets what is stored in the thread storage to the given
374 * callid if it does not match what is already there.
376 * \retval 0 - success
377 * \retval non-zero - failure
379 int ast_callid_threadassoc_change(ast_callid callid);
382 * \brief Adds a known callid to thread storage of the calling thread
384 * \retval 0 - success
385 * \retval non-zero - failure
387 int ast_callid_threadassoc_add(ast_callid callid);
390 * \brief Removes callid from thread storage of the calling thread
392 * \retval 0 - success
393 * \retval non-zero - failure
395 int ast_callid_threadassoc_remove(void);
398 * \brief Checks thread storage for a callid and stores a reference if it exists.
399 * If not, then a new one will be created, bound to the thread, and a reference
400 * to it will be stored.
402 * \param callid pointer to store the callid
403 * \retval 0 - callid was found
404 * \retval 1 - callid was created
405 * \retval -1 - the function failed somehow (presumably memory problems)
407 int ast_callid_threadstorage_auto(ast_callid *callid);
410 * \brief Use in conjunction with ast_callid_threadstorage_auto. Cleans up the
411 * references and if the callid was created by threadstorage_auto, unbinds
412 * the callid from the threadstorage
413 * \param callid The callid set by ast_callid_threadstorage_auto
414 * \param callid_created The integer returned through ast_callid_threadstorage_auto
416 void ast_callid_threadstorage_auto_clean(ast_callid callid, int callid_created);
419 * \brief copy a string representation of the callid into a target string
421 * \param buffer destination of callid string (should be able to store 13 characters or more)
422 * \param buffer_size maximum writable length of the string (Less than 13 will result in truncation)
423 * \param callid Callid for which string is being requested
425 void ast_callid_strnprint(char *buffer, size_t buffer_size, ast_callid callid);
428 * \brief Send a log message to a dynamically registered log level
429 * \param level The log level to send the message to
431 * Like ast_log, the log message may include printf-style formats, and
432 * the data for these must be provided as additional parameters after
438 #define ast_log_dynamic_level(level, ...) ast_log(level, _A_, __VA_ARGS__)
440 #define DEBUG_ATLEAST(level) \
441 (option_debug >= (level) \
442 || (ast_opt_dbg_module \
443 && ((int)ast_debug_get_by_module(AST_MODULE) >= (level) \
444 || (int)ast_debug_get_by_module(__FILE__) >= (level))))
447 * \brief Log a DEBUG message
448 * \param level The minimum value of option_debug for this message
451 #define ast_debug(level, ...) \
453 if (DEBUG_ATLEAST(level)) { \
454 ast_log(AST_LOG_DEBUG, __VA_ARGS__); \
458 extern int ast_verb_sys_level;
460 #define VERBOSITY_ATLEAST(level) ((level) <= ast_verb_sys_level)
462 #define ast_verb(level, ...) \
464 if (VERBOSITY_ATLEAST(level) ) { \
465 __ast_verbose(_A_, level, __VA_ARGS__); \
469 #define ast_verb_callid(level, callid, ...) \
471 if (VERBOSITY_ATLEAST(level) ) { \
472 __ast_verbose_callid(_A_, level, callid, __VA_ARGS__); \
477 * \brief Re-evaluate the system max verbosity level (ast_verb_sys_level).
479 void ast_verb_update(void);
482 * \brief Register this thread's console verbosity level pointer.
484 * \param level Where the verbose level value is.
486 void ast_verb_console_register(int *level);
489 * \brief Unregister this thread's console verbosity level.
491 void ast_verb_console_unregister(void);
494 * \brief Get this thread's console verbosity level.
496 * \return verbosity level of the console.
498 int ast_verb_console_get(void);
501 * \brief Set this thread's console verbosity level.
503 * \param verb_level New level to set.
505 void ast_verb_console_set(int verb_level);
508 * \brief Test if logger is initialized
510 * \retval true if the logger is initialized
512 int ast_is_logger_initialized(void);
515 * \brief Set the maximum number of messages allowed in the processing queue
519 void ast_logger_set_queue_limit(int queue_limit);
522 * \brief Get the maximum number of messages allowed in the processing queue
524 * \return Queue limit
526 int ast_logger_get_queue_limit(void);
530 \page Scope_Trace Scope Trace
532 The Scope Trace facility allows you to instrument code and output scope entry
533 and exit messages with associated data.
536 * You must have used --enable-dev-mode.
537 * In logger.conf, set a logger channel to output the "trace" level.
538 * Instrument your code as specified below.
539 * Use the cli or cli.conf to enable tracing:
540 \verbatim CLI> core set trace <trace_level> [ module ] \endverbatim
542 Its simplest usage requires only 1 macro call that...
543 - Registers a destructor for a special variable that gets called when the
544 variable goes out of scope. Uses the same principle as RAII_VAR.
545 The destructor prints the name of the function with an "exiting" indicator
546 along with an optional message.
547 - Prints the name of the function with an "entering" indicator along with
551 The following code...
553 static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv,
554 struct ast_sip_session *session, const pjmedia_sdp_session *offer)
556 SCOPE_TRACE(1, "%s\n", ast_sip_session_get_name(session));
561 \b [2020-05-17 15:16:51 -0600] TRACE[953402] : --> res_pjsip_session.c:4283 create_local_sdp PJSIP/1173-00000001
562 \b [2020-05-17 15:16:51 -0600] TRACE[953402] : <-- res_pjsip_session.c:4283 create_local_sdp PJSIP/1173-00000001
564 There is one odd bit. There's no way to capture the line number of there the scope exited
565 so it's always going to be the line where SCOPE_TRACE is located.
567 Similar to RAII_VAR, any block scope can be traced including "if", "for", "while", etc.
568 \note "case" statements don't create a scope block by themselves but you can create
569 a block for it, or use the generic trace functions mentioned below.
571 Scope Output and Level:
573 Rather than sending trace messages to the debug facility, a new facility "trace" has been
574 added to logger. A corresponding CLI command "core set trace", and a corresponding "trace"
575 parameter in asterisk.conf were added. This allows a separate log channel to be created
576 just for storing trace messages. The levels are the same as those for debug and verbose.
580 Each time SCOPE_TRACE or SCOPE_TRACE is called, a thread-local indent value is
581 incremented on scope enter, and decremented on scope exit. This allows output
582 like the following (timestamp omitted for brevity):
584 TRACE[953402] : --> res_pjsip_session.c:3940 session_inv_on_tsx_state_changed PJSIP/1173-00000001 TSX State: Proceeding Inv State: CALLING
585 TRACE[953402] : --> res_pjsip_session.c:3680 handle_incoming PJSIP/1173-00000001
586 TRACE[953402] : --> res_pjsip_session.c:3661 handle_incoming_response PJSIP/1173-00000001 Method: INVITE Status: 100
587 TRACE[953402] : --> res_pjsip_session.c:3669 handle_incoming_response PJSIP/1173-00000001 Method: INVITE Status: 100 Supplement: chan_pjsip
588 TRACE[953402] : --> chan_pjsip.c:3265 chan_pjsip_incoming_response_after_media PJSIP/1173-00000001 Method: INVITE Status: 100 After Media
589 TRACE[953402] : --> chan_pjsip.c:3194 chan_pjsip_incoming_response PJSIP/1173-00000001 Method: INVITE Status: 100
590 TRACE[953402] : chan_pjsip.c:3245 chan_pjsip_incoming_response PJSIP/1173-00000001 Method: INVITE Status: 100 Ignored
591 TRACE[953402] : <-- chan_pjsip.c:3194 chan_pjsip_incoming_response PJSIP/1173-00000001 Method: INVITE Status: 100
592 TRACE[953402] : <-- chan_pjsip.c:3265 chan_pjsip_incoming_response_after_media PJSIP/1173-00000001 Method: INVITE Status: 100 After Media
593 TRACE[953402] : <-- res_pjsip_session.c:3669 handle_incoming_response PJSIP/1173-00000001 Method: INVITE Status: 100 Supplement: chan_pjsip
594 TRACE[953402] : <-- res_pjsip_session.c:3661 handle_incoming_response PJSIP/1173-00000001 Method: INVITE Status: 100
595 TRACE[953402] : <-- res_pjsip_session.c:3680 handle_incoming PJSIP/1173-00000001
596 TRACE[953402] : <-- res_pjsip_session.c:3940 session_inv_on_tsx_state_changed PJSIP/1173-00000001 TSX State: Proceeding Inv State: CALLING
598 \note The trace level indicates which messages to print and has no effect on indent.
600 Generic Trace Messages:
602 Sometimes you may just want to print a message to the trace log with the appropriate indent
603 such as when executing a "case" clause in a "switch" statement. For example, the deepest
604 message in the sample output above (chan_pjsip.c:3245) is just a single message instead of
605 an entry/exit message. To do so, you can use the ast_trace macros...
607 ast_trace(1, "%s Method: %.*s Status: %d Ignored\n", ast_sip_session_get_name(session),
608 (int)rdata->msg_info.cseq->method.name.slen, rdata->msg_info.cseq->method.name.ptr, status.code);
611 /note Final note: The trace facility, like debug, is only available when AST_DEVMODE is defined.
616 * \brief Get the trace level for a module
617 * \param module the name of module
618 * \return the trace level
620 unsigned int ast_trace_get_by_module(const char *module);
623 * \brief load logger.conf configuration for console socket connections
625 void ast_init_logger_for_socket_console(void);
627 #define TRACE_ATLEAST(level) \
628 (option_trace >= (level) \
629 || (ast_opt_trace_module \
630 && ((int)ast_trace_get_by_module(AST_MODULE) >= (level) \
631 || (int)ast_trace_get_by_module(__FILE__) >= (level))))
634 * \brief Controls if and when indenting is applied.
636 enum ast_trace_indent_type {
637 /*! Use the existing indent level */
638 AST_TRACE_INDENT_SAME = 0,
639 /*! Increment the indent before printing the message */
640 AST_TRACE_INDENT_INC_BEFORE,
641 /*! Increment the indent after printing the message */
642 AST_TRACE_INDENT_INC_AFTER,
643 /*! Decrement the indent before printing the message */
644 AST_TRACE_INDENT_DEC_BEFORE,
645 /*! Decrement the indent after printing the message */
646 AST_TRACE_INDENT_DEC_AFTER,
647 /*! Set the indent to the one provided */
648 AST_TRACE_INDENT_PROVIDED,
649 /*! Don't use or alter the level */
650 AST_TRACE_INDENT_NONE,
655 void __attribute__((format (printf, 6, 7))) __ast_trace(const char *file, int line, const char *func,
656 enum ast_trace_indent_type indent_type, unsigned long indent, const char* format, ...);
659 * \brief Print a trace message
661 * \param level The trace level
662 * \param indent_type One of the \ref ast_trace_indent_type values
663 * \param ... A printf style format string, optionally with arguments
666 #define ast_trace_raw(level, indent_type, ...) \
667 ast_debug(level < 0 ? __scope_level : level, " " __VA_ARGS__); \
668 if (TRACE_ATLEAST(level < 0 ? __scope_level : level)) { \
669 __ast_trace(_A_, indent_type, 0, " " __VA_ARGS__); \
673 * \brief Print a basic trace message
675 * \param level The trace level
676 * \param ... A printf style format string, optionally with arguments
678 * This will print the file, line and function at the current indent level
680 #define ast_trace(level, ...) \
681 ast_debug(level < 0 ? __scope_level : level, " " __VA_ARGS__); \
682 if (TRACE_ATLEAST(level < 0 ? __scope_level : level)) { \
683 __ast_trace(_A_, AST_TRACE_INDENT_SAME, 0, " " __VA_ARGS__); \
687 * \brief Get the current indent level
689 * \return The current indent level
691 unsigned long _ast_trace_get_indent(void);
692 #define ast_trace_get_indent() _ast_trace_get_indent()
695 * \brief Set the current indent level
697 * \param indent The new indent level
699 void _ast_trace_set_indent(unsigned long indent);
700 #define ast_trace_set_indent(indent) _ast_trace_set_indent(indent)
703 * \brief Increment the indent level
705 * \return The new indent level
707 unsigned long _ast_trace_inc_indent(void);
708 #define ast_trace_inc_indent() _ast_trace_inc_indent()
711 * \brief Decrement the indent level
713 * \return The new indent level
715 unsigned long _ast_trace_dec_indent(void);
716 #define ast_trace_dec_indent() _ast_trace_dec_indent()
719 * \brief Print a trace message with details when a scope is entered or existed.
721 * \param level The trace level
722 * \param ... A printf style format string, optionally with arguments
724 * This will print the file, line and function plus details at the current indent level.
725 * \note Like RAII_VAR, this macro must be called before any code in the scope.
727 * \note The variables used to detect scope change will look like
728 * __scopevar1234__EXIT and __scopevar1234__ENTER.
729 * The ENTER variable and function are needed to prevent mixed code and declaration issues.
730 * If we simple called __ast_trace, then this macro would need to be the last line
731 * of scope variable declaration. The following would fail.
733 * SCOPE_TRACE(1, "Help!\n");
736 #define SCOPE_TRACE(level, ...) \
737 const char *__trace_funcname = __PRETTY_FUNCTION__; \
738 auto void __scopevar ## __LINE__ ## __EXIT(void * v); \
739 void __scopevar ## __LINE__ ## __EXIT(void * v __attribute__((unused))) { \
740 if (TRACE_ATLEAST(level)) { \
741 __ast_trace(__FILE__, __LINE__, __trace_funcname, AST_TRACE_INDENT_DEC_BEFORE, 0, " " __VA_ARGS__); \
744 void *__scopevar ## __LINE__ ## __TRACER __attribute__((cleanup(__scopevar ## __LINE__ ## __EXIT))) = (void *) __PRETTY_FUNCTION__ ; \
745 auto int __scopevar ## __LINE__ ## __ENTER(void); \
746 int __scopevar ## __LINE__ ## __ENTER(void) { \
747 if (TRACE_ATLEAST(level)) { \
748 __ast_trace(__FILE__, __LINE__, __trace_funcname, AST_TRACE_INDENT_INC_AFTER, 0, " " __VA_ARGS__); \
752 int __scopevar ## __LINE__ ## __RETURN __attribute__((unused)) = __scopevar ## __LINE__ ## __ENTER()
755 * \brief Non RAII_VAR Scope Trace macros
756 * The advantage of these macros is that the EXITs will have the actual
757 * line number where the scope exited. Much less code is required as well.
763 * \param level The trace level
764 * \param ... A printf style format string, optionally with arguments
766 #define SCOPE_ENTER(level, ...) \
767 int __scope_level = level; \
768 int __scope_task = 0; \
769 ast_debug(__scope_level, " " __VA_ARGS__); \
770 if (TRACE_ATLEAST(level)) { \
771 __ast_trace(_A_, AST_TRACE_INDENT_INC_AFTER, 0, " " __VA_ARGS__); \
774 #define SCOPE_ENTER_TASK(level, indent, ...) \
775 int __scope_level = level; \
776 int __scope_task = 1; \
777 ast_debug(__scope_level, " " __VA_ARGS__); \
778 if (TRACE_ATLEAST(level)) { \
779 __ast_trace(_A_, AST_TRACE_INDENT_PROVIDED, indent, " " __VA_ARGS__); \
785 * \param ... A printf style format string, optionally with arguments
788 * This macro can be used at the exit points of a statement block since it just prints the message.
790 #define SCOPE_EXIT(...) \
791 ast_debug(__scope_level, " " __VA_ARGS__); \
792 if (TRACE_ATLEAST(__scope_level)) { \
793 __ast_trace(_A_, AST_TRACE_INDENT_DEC_BEFORE, 0, " " __VA_ARGS__); \
794 if (__scope_task) { \
795 _ast_trace_set_indent(0); \
800 * \brief Scope Exit with expression
802 * \param __expr An expression to execute after printing the message
803 * \param ... A printf style format string, optionally with arguments
806 * Handy for getting out of or continuing loops.
810 * SCOPE_ENTER(2, "In a while\n");
812 * SCOPE_EXIT_EXPR(break, "Somethiung broke me\n");
814 * SCOPE_EXIT_EXPR(continue, "Somethiung continued me\n");
819 #define SCOPE_EXIT_EXPR(__expr, ...) \
820 ast_debug(__scope_level, " " __VA_ARGS__); \
821 if (TRACE_ATLEAST(__scope_level)) { \
822 __ast_trace(_A_, AST_TRACE_INDENT_DEC_BEFORE, 0, " " __VA_ARGS__); \
823 if (__scope_task) { \
824 _ast_trace_set_indent(0); \
830 * \brief Scope Exit with return
832 * \param ... A printf style format string, optionally with arguments
835 * This macro can be used at the exit points of a function when no value
836 * needs to be returned.
838 #define SCOPE_EXIT_RTN(...) \
839 ast_debug(__scope_level, " " __VA_ARGS__); \
840 if (TRACE_ATLEAST(__scope_level)) { \
841 __ast_trace(_A_, AST_TRACE_INDENT_DEC_BEFORE, 0, " " __VA_ARGS__); \
842 if (__scope_task) { \
843 _ast_trace_set_indent(0); \
849 * \brief Scope Exit with return value
851 * \param __return_value The return value
852 * \param ... A printf style format string, optionally with arguments
855 * This macro can be used at the exit points of a function when a value
856 * needs to be returned.
858 #define SCOPE_EXIT_RTN_VALUE(__return_value, ...) \
859 ast_debug(__scope_level, " " __VA_ARGS__); \
860 if (TRACE_ATLEAST(__scope_level)) { \
861 __ast_trace(_A_, AST_TRACE_INDENT_DEC_BEFORE, 0, " " __VA_ARGS__); \
862 if (__scope_task) { \
863 _ast_trace_set_indent(0); \
866 return(__return_value)
868 #else /* AST_DEVMODE */
869 #define ast_trace_raw(level, indent_type, ...) \
870 ast_debug(level < 0 ? __scope_level : level, " " __VA_ARGS__)
872 #define ast_trace(level, ...) \
873 ast_debug(level < 0 ? __scope_level : level, " " __VA_ARGS__)
875 #define ast_trace_get_indent() (0)
876 #define ast_trace_set_indent(indent)
877 #define ast_trace_inc_indent()
878 #define ast_trace_dec_indent()
879 #define SCOPE_TRACE(__level, ...)
881 #define SCOPE_ENTER(level, ...) \
882 int __scope_level = level; \
883 ast_debug(level, " " __VA_ARGS__)
885 #define SCOPE_ENTER_TASK(level, indent, ...) \
886 int __scope_level = level; \
887 ast_debug(level, " " __VA_ARGS__)
889 #define SCOPE_EXIT(...) \
890 ast_debug(__scope_level, " " __VA_ARGS__)
892 #define SCOPE_EXIT_EXPR(__expr, ...) \
893 ast_debug(__scope_level, " " __VA_ARGS__); \
896 #define SCOPE_EXIT_RTN(...) \
897 ast_debug(__scope_level, " " __VA_ARGS__); \
900 #define SCOPE_EXIT_RTN_VALUE(__return_value, ...) \
901 ast_debug(__scope_level, " " __VA_ARGS__); \
902 return __return_value
904 #endif /* AST_DEVMODE */
907 * The following macros will print log messages before running
908 * the associated SCOPE_ macro.
911 #define SCOPE_EXIT_LOG(__log_level, ...) \
913 ast_log(__log_level, " " __VA_ARGS__); \
914 SCOPE_EXIT(" " __VA_ARGS__); \
917 #define SCOPE_EXIT_LOG_RTN(__log_level, ...) \
919 ast_log(__log_level, " " __VA_ARGS__); \
920 SCOPE_EXIT_RTN(" " __VA_ARGS__); \
923 #define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level, ...) \
925 ast_log(__log_level, " " __VA_ARGS__); \
926 SCOPE_EXIT_RTN_VALUE(__value, " " __VA_ARGS__); \
929 #define SCOPE_EXIT_LOG_EXPR(__expr, __log_level, ...) \
931 ast_log(__log_level, " " __VA_ARGS__); \
932 SCOPE_EXIT_EXPR(__expr, " " __VA_ARGS__); \
935 #define ast_trace_log(__level, __log_level, ...) \
937 ast_log(__log_level, " " __VA_ARGS__); \
938 ast_trace(__level < 0 ? __scope_level : __level, " " __VA_ARGS__); \
942 #if defined(__cplusplus) || defined(c_plusplus)
946 #endif /* _ASTERISK_LOGGER_H */