#pragma once /*! \defgroup logging Osmocom logging framework * @{ * \file logging.h */ #include #include #include #include #include #include /*! Maximum number of logging contexts */ #define LOG_MAX_CTX 8 /*! Maximum number of logging filters */ #define LOG_MAX_FILTERS 8 #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 levels 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 OSMO_NUM_DLIB 19 /*!< 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 */ }; /*! Log context information, passed to filter */ struct log_context { void *ctx[LOG_MAX_CTX+1]; }; /*! 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_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_COUNT }; /*! Compatibility with older libosmocore versions */ #define LOG_FILTER_ALL (1<'? */ 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_filename(struct log_target *target, int); 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); 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 #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 /*! @} */