2014-06-16 08:13:40 +00:00
|
|
|
#pragma once
|
2010-03-26 13:24:24 +00:00
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \defgroup logging Osmocom logging framework
|
|
|
|
* @{
|
2011-08-16 21:26:52 +00:00
|
|
|
*/
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \file logging.h */
|
|
|
|
|
2010-03-26 13:24:24 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
2011-09-01 14:22:17 +00:00
|
|
|
#include <stdarg.h>
|
2011-03-22 15:36:13 +00:00
|
|
|
#include <osmocom/core/linuxlist.h>
|
2010-03-26 13:24:24 +00:00
|
|
|
|
2011-08-16 21:26:52 +00:00
|
|
|
/*! \brief Maximum number of logging contexts */
|
2010-03-26 13:24:24 +00:00
|
|
|
#define LOG_MAX_CTX 8
|
2011-08-16 21:26:52 +00:00
|
|
|
/*! \brief Maximum number of logging filters */
|
2010-03-26 13:24:24 +00:00
|
|
|
#define LOG_MAX_FILTERS 8
|
|
|
|
|
|
|
|
#define DEBUG
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2016-04-25 10:11:20 +00:00
|
|
|
/*! \brief 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
|
|
|
|
*/
|
2015-11-17 10:52:25 +00:00
|
|
|
#define DEBUGP(ss, fmt, args...) \
|
|
|
|
do { \
|
|
|
|
if (log_check_level(ss, LOGL_DEBUG)) \
|
2016-05-10 13:23:06 +00:00
|
|
|
logp(ss, __BASE_FILE__, __LINE__, 0, fmt, ## args); \
|
2015-11-17 10:52:25 +00:00
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define DEBUGPC(ss, fmt, args...) \
|
|
|
|
do { \
|
|
|
|
if (log_check_level(ss, LOGL_DEBUG)) \
|
2016-05-10 13:23:06 +00:00
|
|
|
logp(ss, __BASE_FILE__, __LINE__, 1, fmt, ## args); \
|
2015-11-17 10:52:25 +00:00
|
|
|
} while(0)
|
|
|
|
|
2010-03-26 13:24:24 +00:00
|
|
|
#else
|
|
|
|
#define DEBUGP(xss, fmt, args...)
|
|
|
|
#define DEBUGPC(ss, fmt, args...)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2012-07-12 07:26:25 +00:00
|
|
|
void osmo_vlogp(int subsys, int level, const char *file, int line,
|
2011-08-27 12:33:19 +00:00
|
|
|
int cont, const char *format, va_list ap);
|
|
|
|
|
2012-07-10 11:10:15 +00:00
|
|
|
void logp(int subsys, const char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
|
2010-03-26 13:24:24 +00:00
|
|
|
|
2011-08-16 21:26:52 +00:00
|
|
|
/*! \brief 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
|
|
|
|
*/
|
2010-03-26 13:24:24 +00:00
|
|
|
#define LOGP(ss, level, fmt, args...) \
|
2015-11-17 10:52:25 +00:00
|
|
|
do { \
|
|
|
|
if (log_check_level(ss, level)) \
|
2016-05-10 13:23:06 +00:00
|
|
|
logp2(ss, level, __BASE_FILE__, __LINE__, 0, fmt, ##args); \
|
2015-11-17 10:52:25 +00:00
|
|
|
} while(0)
|
2011-08-16 21:26:52 +00:00
|
|
|
|
|
|
|
/*! \brief 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
|
|
|
|
*/
|
2010-03-26 13:24:24 +00:00
|
|
|
#define LOGPC(ss, level, fmt, args...) \
|
2015-11-17 10:52:25 +00:00
|
|
|
do { \
|
|
|
|
if (log_check_level(ss, level)) \
|
2016-05-10 13:23:06 +00:00
|
|
|
logp2(ss, level, __BASE_FILE__, __LINE__, 1, fmt, ##args); \
|
2015-11-17 10:52:25 +00:00
|
|
|
} while(0)
|
2010-03-26 13:24:24 +00:00
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief different log levels */
|
|
|
|
#define LOGL_DEBUG 1 /*!< \brief debugging information */
|
2016-04-25 10:11:20 +00:00
|
|
|
#define LOGL_INFO 3 /*!< \brief general information */
|
2011-08-17 12:14:17 +00:00
|
|
|
#define LOGL_NOTICE 5 /*!< \brief abnormal/unexpected condition */
|
|
|
|
#define LOGL_ERROR 7 /*!< \brief error condition, requires user action */
|
|
|
|
#define LOGL_FATAL 8 /*!< \brief fatal, program aborted */
|
2010-03-26 13:24:24 +00:00
|
|
|
|
|
|
|
#define LOG_FILTER_ALL 0x0001
|
|
|
|
|
2011-06-27 08:29:17 +00:00
|
|
|
/* logging levels defined by the library itself */
|
2016-04-25 10:11:20 +00:00
|
|
|
#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 */
|
2016-04-25 16:46:22 +00:00
|
|
|
#define DLGSUP 11 /*!< Generic Subscriber Update Protocol */
|
|
|
|
#define OSMO_NUM_DLIB 11 /*!< Number of logging sub-systems in libraries */
|
2016-04-25 10:11:20 +00:00
|
|
|
|
|
|
|
/*! Configuration of singgle log category / sub-system */
|
2010-03-26 13:24:24 +00:00
|
|
|
struct log_category {
|
2016-04-25 10:11:20 +00:00
|
|
|
uint8_t loglevel; /*!< configured log-level */
|
|
|
|
uint8_t enabled; /*!< is logging enabled? */
|
2010-03-26 13:24:24 +00:00
|
|
|
};
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief Information regarding one logging category */
|
2010-03-26 13:24:24 +00:00
|
|
|
struct log_info_cat {
|
2011-08-17 12:14:17 +00:00
|
|
|
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 */
|
2010-03-26 13:24:24 +00:00
|
|
|
};
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief Log context information, passed to filter */
|
2010-03-26 13:24:24 +00:00
|
|
|
struct log_context {
|
|
|
|
void *ctx[LOG_MAX_CTX+1];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct log_target;
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief Log filter function */
|
2010-03-26 13:24:24 +00:00
|
|
|
typedef int log_filter(const struct log_context *ctx,
|
|
|
|
struct log_target *target);
|
|
|
|
|
2013-06-06 05:33:54 +00:00
|
|
|
struct log_info;
|
|
|
|
struct vty;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief Logging configuration, passed to \ref log_init */
|
2010-03-26 13:24:24 +00:00
|
|
|
struct log_info {
|
2011-08-17 12:14:17 +00:00
|
|
|
/* \brief filter callback function */
|
2010-03-26 13:24:24 +00:00
|
|
|
log_filter *filter_fn;
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief per-category information */
|
2012-09-11 08:31:29 +00:00
|
|
|
const struct log_info_cat *cat;
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief total number of categories */
|
2010-03-26 13:24:24 +00:00
|
|
|
unsigned int num_cat;
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief total number of user categories (not library) */
|
2011-06-27 08:29:17 +00:00
|
|
|
unsigned int num_cat_user;
|
2013-06-06 05:33:54 +00:00
|
|
|
|
2016-04-25 10:11:20 +00:00
|
|
|
/*! \brief filter saving function */
|
2013-06-06 05:33:54 +00:00
|
|
|
log_save_filters *save_fn;
|
2016-04-25 10:11:20 +00:00
|
|
|
/*! \brief filter saving function */
|
2013-06-06 05:33:54 +00:00
|
|
|
log_print_filters *print_fn;
|
2010-03-26 13:24:24 +00:00
|
|
|
};
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief Type of logging target */
|
2011-02-18 19:37:04 +00:00
|
|
|
enum log_target_type {
|
2011-08-17 12:14:17 +00:00
|
|
|
LOG_TGT_TYPE_VTY, /*!< \brief VTY logging */
|
|
|
|
LOG_TGT_TYPE_SYSLOG, /*!< \brief syslog based logging */
|
|
|
|
LOG_TGT_TYPE_FILE, /*!< \brief text file logging */
|
|
|
|
LOG_TGT_TYPE_STDERR, /*!< \brief stderr logging */
|
2013-02-21 05:16:29 +00:00
|
|
|
LOG_TGT_TYPE_STRRB, /*!< \brief osmo_strrb-backed logging */
|
2011-02-18 19:37:04 +00:00
|
|
|
};
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief structure representing a logging target */
|
2010-03-26 13:24:24 +00:00
|
|
|
struct log_target {
|
2011-08-17 12:14:17 +00:00
|
|
|
struct llist_head entry; /*!< \brief linked list */
|
2010-03-26 13:24:24 +00:00
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief Internal data for filtering */
|
2010-03-26 13:24:24 +00:00
|
|
|
int filter_map;
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief Internal data for filtering */
|
2010-03-26 13:24:24 +00:00
|
|
|
void *filter_data[LOG_MAX_FILTERS+1];
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief logging categories */
|
2011-06-27 08:29:17 +00:00
|
|
|
struct log_category *categories;
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief global log level */
|
2010-03-26 13:24:24 +00:00
|
|
|
uint8_t loglevel;
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief should color be used when printing log messages? */
|
2011-07-16 09:57:53 +00:00
|
|
|
unsigned int use_color:1;
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief should log messages be prefixed with a timestamp? */
|
2011-07-16 09:57:53 +00:00
|
|
|
unsigned int print_timestamp:1;
|
2012-09-11 09:24:51 +00:00
|
|
|
/*! \brief should log messages be prefixed with a filename? */
|
|
|
|
unsigned int print_filename:1;
|
2014-12-05 08:35:30 +00:00
|
|
|
/*! \brief should log messages be prefixed with a category name? */
|
|
|
|
unsigned int print_category:1;
|
|
|
|
/*! \brief should log messages be prefixed with an extended timestamp? */
|
|
|
|
unsigned int print_ext_timestamp:1;
|
2010-03-26 13:24:24 +00:00
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief the type of this log taget */
|
2011-02-18 19:37:04 +00:00
|
|
|
enum log_target_type type;
|
|
|
|
|
2010-03-26 13:24:24 +00:00
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
FILE *out;
|
2010-08-25 17:24:00 +00:00
|
|
|
const char *fname;
|
2010-08-25 12:55:44 +00:00
|
|
|
} tgt_file;
|
2010-03-26 13:24:24 +00:00
|
|
|
|
|
|
|
struct {
|
|
|
|
int priority;
|
2011-02-18 19:37:04 +00:00
|
|
|
int facility;
|
2010-03-26 13:24:24 +00:00
|
|
|
} tgt_syslog;
|
|
|
|
|
|
|
|
struct {
|
|
|
|
void *vty;
|
|
|
|
} tgt_vty;
|
2013-02-21 05:16:29 +00:00
|
|
|
|
|
|
|
struct {
|
|
|
|
void *rb;
|
|
|
|
} tgt_rb;
|
2010-03-26 13:24:24 +00:00
|
|
|
};
|
|
|
|
|
2011-08-17 12:14:17 +00:00
|
|
|
/*! \brief call-back function to be called when the logging framework
|
2016-12-02 12:52:59 +00:00
|
|
|
* wants to log a fully formatted string
|
2013-02-15 12:27:59 +00:00
|
|
|
* \param[in] target logging target
|
2011-08-17 12:14:17 +00:00
|
|
|
* \param[in] level log level of currnet message
|
|
|
|
* \param[in] string the string that is to be written to the log
|
|
|
|
*/
|
2011-02-17 14:52:39 +00:00
|
|
|
void (*output) (struct log_target *target, unsigned int level,
|
|
|
|
const char *string);
|
2016-12-02 12:52:59 +00:00
|
|
|
|
|
|
|
/*! \brief 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);
|
2010-03-26 13:24:24 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* use the above macros */
|
2012-07-10 11:10:15 +00:00
|
|
|
void logp2(int subsys, unsigned int level, const char *file,
|
2010-03-26 13:24:24 +00:00
|
|
|
int line, int cont, const char *format, ...)
|
|
|
|
__attribute__ ((format (printf, 6, 7)));
|
2011-06-27 08:29:17 +00:00
|
|
|
int log_init(const struct log_info *inf, void *talloc_ctx);
|
2016-04-20 08:41:27 +00:00
|
|
|
void log_fini(void);
|
2015-11-17 10:52:24 +00:00
|
|
|
int log_check_level(int subsys, unsigned int level);
|
2010-03-26 13:24:24 +00:00
|
|
|
|
|
|
|
/* 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);
|
2014-12-05 08:35:30 +00:00
|
|
|
void log_set_print_extended_timestamp(struct log_target *target, int);
|
2010-03-26 13:24:24 +00:00
|
|
|
void log_set_print_timestamp(struct log_target *target, int);
|
2012-09-11 09:24:51 +00:00
|
|
|
void log_set_print_filename(struct log_target *target, int);
|
2014-12-05 08:35:30 +00:00
|
|
|
void log_set_print_category(struct log_target *target, int);
|
2010-03-26 13:24:24 +00:00
|
|
|
void log_set_log_level(struct log_target *target, int log_level);
|
|
|
|
void log_parse_category_mask(struct log_target *target, const char* mask);
|
|
|
|
int log_parse_level(const char *lvl);
|
2010-05-11 09:19:40 +00:00
|
|
|
const char *log_level_str(unsigned int lvl);
|
2010-03-26 13:24:24 +00:00
|
|
|
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);
|
2010-08-25 17:24:00 +00:00
|
|
|
void log_target_destroy(struct log_target *target);
|
2010-03-26 13:24:24 +00:00
|
|
|
struct log_target *log_target_create_stderr(void);
|
2010-08-25 17:24:00 +00:00
|
|
|
struct log_target *log_target_create_file(const char *fname);
|
2011-02-17 14:56:56 +00:00
|
|
|
struct log_target *log_target_create_syslog(const char *ident, int option,
|
|
|
|
int facility);
|
2010-08-25 17:24:00 +00:00
|
|
|
int log_target_file_reopen(struct log_target *tgt);
|
2013-03-18 18:01:40 +00:00
|
|
|
int log_targets_reopen(void);
|
2010-08-25 17:24:00 +00:00
|
|
|
|
2010-03-26 13:24:24 +00:00
|
|
|
void log_add_target(struct log_target *target);
|
|
|
|
void log_del_target(struct log_target *target);
|
|
|
|
|
2011-03-09 12:05:08 +00:00
|
|
|
/* Generate command string for VTY use */
|
|
|
|
const char *log_vty_command_string(const struct log_info *info);
|
|
|
|
const char *log_vty_command_description(const struct log_info *info);
|
2010-05-11 14:39:22 +00:00
|
|
|
|
2011-02-18 19:37:04 +00:00
|
|
|
struct log_target *log_target_find(int type, const char *fname);
|
|
|
|
extern struct llist_head osmo_log_target_list;
|
|
|
|
|
2012-04-18 19:53:23 +00:00
|
|
|
/*! @} */
|