| #pragma once |
| |
| /*! \defgroup logging Osmocom logging framework |
| * @{ |
| * \file logging.h */ |
| |
| #include <stdio.h> |
| #include <stdint.h> |
| #include <stdarg.h> |
| #include <stdbool.h> |
| #include <osmocom/core/defs.h> |
| #include <osmocom/core/linuxlist.h> |
| |
| #ifndef DEBUG |
| #define DEBUG |
| #endif |
| |
| #ifdef DEBUG |
| /*! Log a debug message through the Osmocom logging framework |
| * \param[in] ss logging subsystem (e.g. \ref DLGLOBAL) |
| * \param[in] fmt format string |
| * \param[in] args variable argument list |
| */ |
| #define DEBUGP(ss, fmt, args...) LOGP(ss, LOGL_DEBUG, fmt, ##args) |
| #define DEBUGPC(ss, fmt, args...) LOGPC(ss, LOGL_DEBUG, fmt, ##args) |
| #else |
| #define DEBUGP(xss, fmt, args...) |
| #define DEBUGPC(ss, fmt, args...) |
| #endif |
| |
| |
| void osmo_vlogp(int subsys, int level, const char *file, int line, |
| int cont, const char *format, va_list ap); |
| |
| void logp(int subsys, const char *file, int line, int cont, const char *format, ...) OSMO_DEPRECATED("Use DEBUGP* macros instead"); |
| |
| /*! Log a new message through the Osmocom logging framework |
| * \param[in] ss logging subsystem (e.g. \ref DLGLOBAL) |
| * \param[in] level logging level (e.g. \ref LOGL_NOTICE) |
| * \param[in] fmt format string |
| * \param[in] args variable argument list |
| */ |
| #define LOGP(ss, level, fmt, args...) \ |
| LOGPSRC(ss, level, NULL, 0, fmt, ## args) |
| |
| /*! Continue a log message through the Osmocom logging framework |
| * \param[in] ss logging subsystem (e.g. \ref DLGLOBAL) |
| * \param[in] level logging level (e.g. \ref LOGL_NOTICE) |
| * \param[in] fmt format string |
| * \param[in] args variable argument list |
| */ |
| #define LOGPC(ss, level, fmt, args...) \ |
| do { \ |
| if (log_check_level(ss, level)) \ |
| logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args); \ |
| } while(0) |
| |
| /*! Log through the Osmocom logging framework with explicit source. |
| * If caller_file is passed as NULL, __FILE__ and __LINE__ are used |
| * instead of caller_file and caller_line (so that this macro here defines |
| * both cases in the same place, and to catch cases where callers fail to pass |
| * a non-null filename string). |
| * \param[in] ss logging subsystem (e.g. \ref DLGLOBAL) |
| * \param[in] level logging level (e.g. \ref LOGL_NOTICE) |
| * \param[in] caller_file caller's source file string (e.g. __FILE__) |
| * \param[in] caller_line caller's source line nr (e.g. __LINE__) |
| * \param[in] fmt format string |
| * \param[in] args variable argument list |
| */ |
| #define LOGPSRC(ss, level, caller_file, caller_line, fmt, args...) \ |
| LOGPSRCC(ss, level, caller_file, caller_line, 0, fmt, ##args) |
| |
| /*! Log through the Osmocom logging framework with explicit source. |
| * If caller_file is passed as NULL, __FILE__ and __LINE__ are used |
| * instead of caller_file and caller_line (so that this macro here defines |
| * both cases in the same place, and to catch cases where callers fail to pass |
| * a non-null filename string). |
| * \param[in] ss logging subsystem (e.g. \ref DLGLOBAL) |
| * \param[in] level logging level (e.g. \ref LOGL_NOTICE) |
| * \param[in] caller_file caller's source file string (e.g. __FILE__) |
| * \param[in] caller_line caller's source line nr (e.g. __LINE__) |
| * \param[in] cont continuation (1) or new line (0) |
| * \param[in] fmt format string |
| * \param[in] args variable argument list |
| */ |
| #define LOGPSRCC(ss, level, caller_file, caller_line, cont, fmt, args...) \ |
| do { \ |
| if (log_check_level(ss, level)) {\ |
| if (caller_file) \ |
| logp2(ss, level, caller_file, caller_line, cont, fmt, ##args); \ |
| else \ |
| logp2(ss, level, __FILE__, __LINE__, cont, fmt, ##args); \ |
| }\ |
| } while(0) |
| |
| /*! different log levels */ |
| #define LOGL_DEBUG 1 /*!< debugging information */ |
| #define LOGL_INFO 3 /*!< general information */ |
| #define LOGL_NOTICE 5 /*!< abnormal/unexpected condition */ |
| #define LOGL_ERROR 7 /*!< error condition, requires user action */ |
| #define LOGL_FATAL 8 /*!< fatal, program aborted */ |
| |
| /* logging subsystems defined by the library itself */ |
| #define DLGLOBAL -1 /*!< global logging */ |
| #define DLLAPD -2 /*!< LAPD implementation */ |
| #define DLINP -3 /*!< (A-bis) Input sub-system */ |
| #define DLMUX -4 /*!< Osmocom Multiplex (Osmux) */ |
| #define DLMI -5 /*!< ISDN-layer below input sub-system */ |
| #define DLMIB -6 /*!< ISDN layer B-channel */ |
| #define DLSMS -7 /*!< SMS sub-system */ |
| #define DLCTRL -8 /*!< Control Interface */ |
| #define DLGTP -9 /*!< GTP (GPRS Tunneling Protocol */ |
| #define DLSTATS -10 /*!< Statistics */ |
| #define DLGSUP -11 /*!< Generic Subscriber Update Protocol */ |
| #define DLOAP -12 /*!< Osmocom Authentication Protocol */ |
| #define DLSS7 -13 /*!< Osmocom SS7 */ |
| #define DLSCCP -14 /*!< Osmocom SCCP */ |
| #define DLSUA -15 /*!< Osmocom SUA */ |
| #define DLM3UA -16 /*!< Osmocom M3UA */ |
| #define DLMGCP -17 /*!< Osmocom MGCP */ |
| #define DLJIBUF -18 /*!< Osmocom Jitter Buffer */ |
| #define DLRSPRO -19 /*!< Osmocom Remote SIM Protocol */ |
| #define DLNS -20 /*!< Osmocom NS layer */ |
| #define DLBSSGP -21 /*!< Osmocom BSSGP layer */ |
| #define DLNSDATA -22 /*!< Osmocom NS layer data pdus */ |
| #define DLNSSIGNAL -23 /*!< Osmocom NS layer signal pdus */ |
| #define OSMO_NUM_DLIB 23 /*!< Number of logging sub-systems in libraries */ |
| |
| /* Colors that can be used in log_info_cat.color */ |
| #define OSMO_LOGCOLOR_NORMAL NULL |
| #define OSMO_LOGCOLOR_RED "\033[1;31m" |
| #define OSMO_LOGCOLOR_GREEN "\033[1;32m" |
| #define OSMO_LOGCOLOR_YELLOW "\033[1;33m" |
| #define OSMO_LOGCOLOR_BLUE "\033[1;34m" |
| #define OSMO_LOGCOLOR_PURPLE "\033[1;35m" |
| #define OSMO_LOGCOLOR_CYAN "\033[1;36m" |
| #define OSMO_LOGCOLOR_DARKRED "\033[31m" |
| #define OSMO_LOGCOLOR_DARKGREEN "\033[32m" |
| #define OSMO_LOGCOLOR_DARKYELLOW "\033[33m" |
| #define OSMO_LOGCOLOR_DARKBLUE "\033[34m" |
| #define OSMO_LOGCOLOR_DARKPURPLE "\033[35m" |
| #define OSMO_LOGCOLOR_DARKCYAN "\033[36m" |
| #define OSMO_LOGCOLOR_DARKGREY "\033[1;30m" |
| #define OSMO_LOGCOLOR_GREY "\033[37m" |
| #define OSMO_LOGCOLOR_BRIGHTWHITE "\033[1;37m" |
| #define OSMO_LOGCOLOR_END "\033[0;m" |
| |
| /*! Configuration of single log category / sub-system */ |
| struct log_category { |
| uint8_t loglevel; /*!< configured log-level */ |
| uint8_t enabled; /*!< is logging enabled? */ |
| }; |
| |
| /*! Information regarding one logging category */ |
| struct log_info_cat { |
| const char *name; /*!< name of category */ |
| const char *color; /*!< color string for cateyory */ |
| const char *description; /*!< description text */ |
| uint8_t loglevel; /*!< currently selected log-level */ |
| uint8_t enabled; /*!< is this category enabled or not */ |
| }; |
| |
| /*! Indexes to indicate the object currently acted upon. |
| * Array indexes for the global \a log_context array. */ |
| enum log_ctx_index { |
| LOG_CTX_GB_NSVC, |
| LOG_CTX_GB_BVC, |
| LOG_CTX_BSC_SUBSCR, |
| LOG_CTX_VLR_SUBSCR, |
| LOG_CTX_L1_SAPI, |
| LOG_CTX_GB_NSE, |
| _LOG_CTX_COUNT |
| }; |
| |
| /*! Indexes to indicate objects that should be logged. |
| * Array indexes to log_target->filter_data and bit indexes for |
| * log_target->filter_map. */ |
| enum log_filter_index { |
| LOG_FLT_ALL, |
| LOG_FLT_GB_NSVC, |
| LOG_FLT_GB_BVC, |
| LOG_FLT_BSC_SUBSCR, |
| LOG_FLT_VLR_SUBSCR, |
| LOG_FLT_L1_SAPI, |
| LOG_FLT_GB_NSE, |
| _LOG_FLT_COUNT |
| }; |
| |
| /*! Maximum number of logging contexts */ |
| #define LOG_MAX_CTX _LOG_CTX_COUNT |
| /*! Maximum number of logging filters */ |
| #define LOG_MAX_FILTERS _LOG_FLT_COUNT |
| |
| /*! Log context information, passed to filter */ |
| struct log_context { |
| void *ctx[LOG_MAX_CTX+1]; |
| }; |
| |
| /*! Compatibility with older libosmocore versions */ |
| #define LOG_FILTER_ALL (1<<LOG_FLT_ALL) |
| /*! Compatibility with older libosmocore versions */ |
| #define GPRS_CTX_NSVC LOG_CTX_GB_NSVC |
| /*! Compatibility with older libosmocore versions */ |
| #define GPRS_CTX_BVC LOG_CTX_GB_BVC |
| /*! Indexes to indicate the object currently acted upon. |
| * Array indexes for the global \a log_context array. */ |
| |
| struct log_target; |
| |
| /*! Log filter function */ |
| typedef int log_filter(const struct log_context *ctx, |
| struct log_target *target); |
| |
| struct log_info; |
| struct vty; |
| struct gsmtap_inst; |
| |
| typedef void log_print_filters(struct vty *vty, |
| const struct log_info *info, |
| const struct log_target *tgt); |
| |
| typedef void log_save_filters(struct vty *vty, |
| const struct log_info *info, |
| const struct log_target *tgt); |
| |
| /*! Logging configuration, passed to \ref log_init */ |
| struct log_info { |
| /* filter callback function */ |
| log_filter *filter_fn; |
| |
| /*! per-category information */ |
| const struct log_info_cat *cat; |
| /*! total number of categories */ |
| unsigned int num_cat; |
| /*! total number of user categories (not library) */ |
| unsigned int num_cat_user; |
| |
| /*! filter saving function */ |
| log_save_filters *save_fn; |
| /*! filter saving function */ |
| log_print_filters *print_fn; |
| }; |
| |
| /*! Type of logging target */ |
| enum log_target_type { |
| LOG_TGT_TYPE_VTY, /*!< VTY logging */ |
| LOG_TGT_TYPE_SYSLOG, /*!< syslog based logging */ |
| LOG_TGT_TYPE_FILE, /*!< text file logging */ |
| LOG_TGT_TYPE_STDERR, /*!< stderr logging */ |
| LOG_TGT_TYPE_STRRB, /*!< osmo_strrb-backed logging */ |
| LOG_TGT_TYPE_GSMTAP, /*!< GSMTAP network logging */ |
| LOG_TGT_TYPE_SYSTEMD, /*!< systemd journal logging */ |
| }; |
| |
| /*! Whether/how to log the source filename (and line number). */ |
| enum log_filename_type { |
| LOG_FILENAME_NONE, |
| LOG_FILENAME_PATH, |
| LOG_FILENAME_BASENAME, |
| }; |
| |
| /*! Where on a log line source file and line should be logged. */ |
| enum log_filename_pos { |
| LOG_FILENAME_POS_HEADER_END, |
| LOG_FILENAME_POS_LINE_END, |
| }; |
| |
| /*! structure representing a logging target */ |
| struct log_target { |
| struct llist_head entry; /*!< linked list */ |
| |
| /*! Internal data for filtering */ |
| int filter_map; |
| /*! Internal data for filtering */ |
| void *filter_data[LOG_MAX_FILTERS+1]; |
| |
| /*! logging categories */ |
| struct log_category *categories; |
| |
| /*! global log level */ |
| uint8_t loglevel; |
| /*! should color be used when printing log messages? */ |
| unsigned int use_color:1; |
| /*! should log messages be prefixed with a timestamp? */ |
| unsigned int print_timestamp:1; |
| /*! should log messages be prefixed with the logger Thread ID? */ |
| unsigned int print_tid:1; |
| /*! DEPRECATED: use print_filename2 instead. */ |
| unsigned int print_filename:1; |
| /*! should log messages be prefixed with a category name? */ |
| unsigned int print_category:1; |
| /*! should log messages be prefixed with an extended timestamp? */ |
| unsigned int print_ext_timestamp:1; |
| |
| /*! the type of this log taget */ |
| enum log_target_type type; |
| |
| union { |
| struct { |
| FILE *out; |
| const char *fname; |
| } tgt_file; |
| |
| struct { |
| int priority; |
| int facility; |
| } tgt_syslog; |
| |
| struct { |
| void *vty; |
| } tgt_vty; |
| |
| struct { |
| void *rb; |
| } tgt_rb; |
| |
| struct { |
| struct gsmtap_inst *gsmtap_inst; |
| const char *ident; |
| const char *hostname; |
| } tgt_gsmtap; |
| |
| struct { |
| bool raw; |
| } sd_journal; |
| }; |
| |
| /*! call-back function to be called when the logging framework |
| * wants to log a fully formatted string |
| * \param[in] target logging target |
| * \param[in] level log level of currnet message |
| * \param[in] string the string that is to be written to the log |
| */ |
| void (*output) (struct log_target *target, unsigned int level, |
| const char *string); |
| |
| /*! alternative call-back function to which the logging |
| * framework passes the unfortmatted input arguments, |
| * i.e. bypassing the internal string formatter |
| * \param[in] target logging target |
| * \param[in] subsys logging sub-system |
| * \param[in] level logging level |
| * \param[in] file soure code file name |
| * \param[in] line source code file line number |
| * \param[in] cont continuation of previous statement? |
| * \param[in] format format string |
| * \param[in] ap vararg list of printf arguments |
| */ |
| void (*raw_output)(struct log_target *target, int subsys, |
| unsigned int level, const char *file, int line, |
| int cont, const char *format, va_list ap); |
| |
| /* Should the log level be printed? */ |
| bool print_level; |
| /* Should we print the subsys in hex like '<000b>'? */ |
| bool print_category_hex; |
| /* Should we print the source file and line, and in which way? */ |
| enum log_filename_type print_filename2; |
| /* Where on a log line to put the source file info. */ |
| enum log_filename_pos print_filename_pos; |
| }; |
| |
| /* use the above macros */ |
| void logp2(int subsys, unsigned int level, const char *file, |
| int line, int cont, const char *format, ...) |
| __attribute__ ((format (printf, 6, 7))); |
| int log_init(const struct log_info *inf, void *talloc_ctx); |
| void log_fini(void); |
| int log_check_level(int subsys, unsigned int level); |
| |
| /* context management */ |
| void log_reset_context(void); |
| int log_set_context(uint8_t ctx, void *value); |
| |
| /* filter on the targets */ |
| void log_set_all_filter(struct log_target *target, int); |
| |
| void log_set_use_color(struct log_target *target, int); |
| void log_set_print_extended_timestamp(struct log_target *target, int); |
| void log_set_print_timestamp(struct log_target *target, int); |
| void log_set_print_tid(struct log_target *target, int); |
| void log_set_print_filename(struct log_target *target, int) OSMO_DEPRECATED("Use log_set_print_filename2() instead"); |
| void log_set_print_filename2(struct log_target *target, enum log_filename_type lft); |
| void log_set_print_filename_pos(struct log_target *target, enum log_filename_pos pos); |
| void log_set_print_category(struct log_target *target, int); |
| void log_set_print_category_hex(struct log_target *target, int); |
| void log_set_print_level(struct log_target *target, int); |
| void log_set_log_level(struct log_target *target, int log_level); |
| void log_parse_category_mask(struct log_target *target, const char* mask); |
| const char* log_category_name(int subsys); |
| int log_parse_level(const char *lvl) OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE; |
| const char *log_level_str(unsigned int lvl) OSMO_DEPRECATED_OUTSIDE_LIBOSMOCORE; |
| int log_parse_category(const char *category); |
| void log_set_category_filter(struct log_target *target, int category, |
| int enable, int level); |
| |
| /* management of the targets */ |
| struct log_target *log_target_create(void); |
| void log_target_destroy(struct log_target *target); |
| struct log_target *log_target_create_stderr(void); |
| struct log_target *log_target_create_file(const char *fname); |
| struct log_target *log_target_create_syslog(const char *ident, int option, |
| int facility); |
| struct log_target *log_target_create_gsmtap(const char *host, uint16_t port, |
| const char *ident, |
| bool ofd_wq_mode, |
| bool add_sink); |
| struct log_target *log_target_create_systemd(bool raw); |
| void log_target_systemd_set_raw(struct log_target *target, bool raw); |
| int log_target_file_reopen(struct log_target *tgt); |
| int log_targets_reopen(void); |
| |
| void log_add_target(struct log_target *target); |
| void log_del_target(struct log_target *target); |
| |
| struct log_target *log_target_find(int type, const char *fname); |
| |
| void log_enable_multithread(void); |
| |
| void log_tgt_mutex_lock_impl(void); |
| void log_tgt_mutex_unlock_impl(void); |
| #define LOG_MTX_DEBUG 0 |
| #if LOG_MTX_DEBUG |
| #include <pthread.h> |
| #define log_tgt_mutex_lock() do { fprintf(stderr, "[%lu] %s:%d [%s] lock\n", pthread_self(), __FILE__, __LINE__, __func__); log_tgt_mutex_lock_impl(); } while (0) |
| #define log_tgt_mutex_unlock() do { fprintf(stderr, "[%lu] %s:%d [%s] unlock\n", pthread_self(), __FILE__, __LINE__, __func__); log_tgt_mutex_unlock_impl(); } while (0) |
| #else |
| #define log_tgt_mutex_lock() log_tgt_mutex_lock_impl() |
| #define log_tgt_mutex_unlock() log_tgt_mutex_unlock_impl() |
| #endif |
| |
| /*! @} */ |