mirror of https://gerrit.osmocom.org/libosmocore
doxygen documentation for logging framework
This commit is contained in:
parent
ba6988bd89
commit
18fc465b7f
|
@ -1,10 +1,12 @@
|
||||||
#ifndef _OSMOCORE_LOGGING_H
|
#ifndef _OSMOCORE_LOGGING_H
|
||||||
#define _OSMOCORE_LOGGING_H
|
#define _OSMOCORE_LOGGING_H
|
||||||
|
|
||||||
/*! \file logging.h
|
/*! \defgroup logging Osmocom logging framework
|
||||||
* \brief Osmocom logging framework
|
* @{
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*! \file logging.h */
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <osmocom/core/linuxlist.h>
|
#include <osmocom/core/linuxlist.h>
|
||||||
|
@ -45,12 +47,12 @@ void logp(int subsys, char *file, int line, int cont, const char *format, ...) _
|
||||||
#define LOGPC(ss, level, fmt, args...) \
|
#define LOGPC(ss, level, fmt, args...) \
|
||||||
logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args)
|
logp2(ss, level, __FILE__, __LINE__, 1, fmt, ##args)
|
||||||
|
|
||||||
/* different levels */
|
/*! \brief different log levels */
|
||||||
#define LOGL_DEBUG 1 /* debugging information */
|
#define LOGL_DEBUG 1 /*!< \brief debugging information */
|
||||||
#define LOGL_INFO 3
|
#define LOGL_INFO 3
|
||||||
#define LOGL_NOTICE 5 /* abnormal/unexpected condition */
|
#define LOGL_NOTICE 5 /*!< \brief abnormal/unexpected condition */
|
||||||
#define LOGL_ERROR 7 /* error condition, requires user action */
|
#define LOGL_ERROR 7 /*!< \brief error condition, requires user action */
|
||||||
#define LOGL_FATAL 8 /* fatal, program aborted */
|
#define LOGL_FATAL 8 /*!< \brief fatal, program aborted */
|
||||||
|
|
||||||
#define LOG_FILTER_ALL 0x0001
|
#define LOG_FILTER_ALL 0x0001
|
||||||
|
|
||||||
|
@ -68,53 +70,67 @@ struct log_category {
|
||||||
uint8_t enabled;
|
uint8_t enabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! \brief Information regarding one logging category */
|
||||||
struct log_info_cat {
|
struct log_info_cat {
|
||||||
const char *name;
|
const char *name; /*!< name of category */
|
||||||
const char *color;
|
const char *color; /*!< color string for cateyory */
|
||||||
const char *description;
|
const char *description; /*!< description text */
|
||||||
uint8_t loglevel;
|
uint8_t loglevel; /*!< currently selected log-level */
|
||||||
uint8_t enabled;
|
uint8_t enabled; /*!< is this category enabled or not */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* log context information, passed to filter */
|
/*! \brief Log context information, passed to filter */
|
||||||
struct log_context {
|
struct log_context {
|
||||||
void *ctx[LOG_MAX_CTX+1];
|
void *ctx[LOG_MAX_CTX+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct log_target;
|
struct log_target;
|
||||||
|
|
||||||
|
/*! \brief Log filter function */
|
||||||
typedef int log_filter(const struct log_context *ctx,
|
typedef int log_filter(const struct log_context *ctx,
|
||||||
struct log_target *target);
|
struct log_target *target);
|
||||||
|
|
||||||
|
/*! \brief Logging configuration, passed to \ref log_init */
|
||||||
struct log_info {
|
struct log_info {
|
||||||
/* filter callback function */
|
/* \brief filter callback function */
|
||||||
log_filter *filter_fn;
|
log_filter *filter_fn;
|
||||||
|
|
||||||
/* per-category information */
|
/*! \brief per-category information */
|
||||||
struct log_info_cat *cat;
|
struct log_info_cat *cat;
|
||||||
|
/*! \brief total number of categories */
|
||||||
unsigned int num_cat;
|
unsigned int num_cat;
|
||||||
|
/*! \brief total number of user categories (not library) */
|
||||||
unsigned int num_cat_user;
|
unsigned int num_cat_user;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! \brief Type of logging target */
|
||||||
enum log_target_type {
|
enum log_target_type {
|
||||||
LOG_TGT_TYPE_VTY,
|
LOG_TGT_TYPE_VTY, /*!< \brief VTY logging */
|
||||||
LOG_TGT_TYPE_SYSLOG,
|
LOG_TGT_TYPE_SYSLOG, /*!< \brief syslog based logging */
|
||||||
LOG_TGT_TYPE_FILE,
|
LOG_TGT_TYPE_FILE, /*!< \brief text file logging */
|
||||||
LOG_TGT_TYPE_STDERR,
|
LOG_TGT_TYPE_STDERR, /*!< \brief stderr logging */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! \brief structure representing a logging target */
|
||||||
struct log_target {
|
struct log_target {
|
||||||
struct llist_head entry;
|
struct llist_head entry; /*!< \brief linked list */
|
||||||
|
|
||||||
|
/*! \brief Internal data for filtering */
|
||||||
int filter_map;
|
int filter_map;
|
||||||
|
/*! \brief Internal data for filtering */
|
||||||
void *filter_data[LOG_MAX_FILTERS+1];
|
void *filter_data[LOG_MAX_FILTERS+1];
|
||||||
|
|
||||||
|
/*! \brief logging categories */
|
||||||
struct log_category *categories;
|
struct log_category *categories;
|
||||||
|
|
||||||
|
/*! \brief global log level */
|
||||||
uint8_t loglevel;
|
uint8_t loglevel;
|
||||||
|
/*! \brief should color be used when printing log messages? */
|
||||||
unsigned int use_color:1;
|
unsigned int use_color:1;
|
||||||
|
/*! \brief should log messages be prefixed with a timestamp? */
|
||||||
unsigned int print_timestamp:1;
|
unsigned int print_timestamp:1;
|
||||||
|
|
||||||
|
/*! \brief the type of this log taget */
|
||||||
enum log_target_type type;
|
enum log_target_type type;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
@ -133,6 +149,12 @@ struct log_target {
|
||||||
} tgt_vty;
|
} tgt_vty;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! \brief call-back function to be called when the logging framework
|
||||||
|
* wants to log somethnig.
|
||||||
|
* \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,
|
void (*output) (struct log_target *target, unsigned int level,
|
||||||
const char *string);
|
const char *string);
|
||||||
};
|
};
|
||||||
|
@ -169,12 +191,7 @@ struct log_target *log_target_create_syslog(const char *ident, int option,
|
||||||
int facility);
|
int facility);
|
||||||
int log_target_file_reopen(struct log_target *tgt);
|
int log_target_file_reopen(struct log_target *tgt);
|
||||||
|
|
||||||
/*! \brief Add a new logging target
|
|
||||||
*/
|
|
||||||
void log_add_target(struct log_target *target);
|
void log_add_target(struct log_target *target);
|
||||||
|
|
||||||
/*! \brief Deelete an existing logging target
|
|
||||||
*/
|
|
||||||
void log_del_target(struct log_target *target);
|
void log_del_target(struct log_target *target);
|
||||||
|
|
||||||
/* Generate command string for VTY use */
|
/* Generate command string for VTY use */
|
||||||
|
@ -184,4 +201,6 @@ const char *log_vty_command_description(const struct log_info *info);
|
||||||
struct log_target *log_target_find(int type, const char *fname);
|
struct log_target *log_target_find(int type, const char *fname);
|
||||||
extern struct llist_head osmo_log_target_list;
|
extern struct llist_head osmo_log_target_list;
|
||||||
|
|
||||||
|
/*! }@ */
|
||||||
|
|
||||||
#endif /* _OSMOCORE_LOGGING_H */
|
#endif /* _OSMOCORE_LOGGING_H */
|
||||||
|
|
|
@ -20,6 +20,12 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* \addtogroup logging
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* \file logging.c */
|
||||||
|
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
@ -113,16 +119,22 @@ static int subsys_lib2index(int subsys)
|
||||||
return (subsys * -1) + (osmo_log_info->num_cat_user-1);
|
return (subsys * -1) + (osmo_log_info->num_cat_user-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Parse a human-readable log level into a numeric value */
|
||||||
int log_parse_level(const char *lvl)
|
int log_parse_level(const char *lvl)
|
||||||
{
|
{
|
||||||
return get_string_value(loglevel_strs, lvl);
|
return get_string_value(loglevel_strs, lvl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief convert a numeric log level into human-readable string */
|
||||||
const char *log_level_str(unsigned int lvl)
|
const char *log_level_str(unsigned int lvl)
|
||||||
{
|
{
|
||||||
return get_value_string(loglevel_strs, lvl);
|
return get_value_string(loglevel_strs, lvl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief parse a human-readable log category into numeric form
|
||||||
|
* \param[in] category human-readable log category name
|
||||||
|
* \returns numeric category value, or -EINVAL otherwise
|
||||||
|
*/
|
||||||
int log_parse_category(const char *category)
|
int log_parse_category(const char *category)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -137,8 +149,10 @@ int log_parse_category(const char *category)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*! \brief parse the log category mask
|
||||||
* Parse the category mask.
|
* \param[in] target log target to be configured
|
||||||
|
* \param[in] _mask log category mask string
|
||||||
|
*
|
||||||
* The format can be this: category1:category2:category3
|
* The format can be this: category1:category2:category3
|
||||||
* or category1,2:category2,3:...
|
* or category1,2:category2,3:...
|
||||||
*/
|
*/
|
||||||
|
@ -312,21 +326,38 @@ void logp2(int subsys, unsigned int level, char *file, int line, int cont, const
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Register a new log target with the logging core
|
||||||
|
* \param[in] target Log target to be registered
|
||||||
|
*/
|
||||||
void log_add_target(struct log_target *target)
|
void log_add_target(struct log_target *target)
|
||||||
{
|
{
|
||||||
llist_add_tail(&target->entry, &osmo_log_target_list);
|
llist_add_tail(&target->entry, &osmo_log_target_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Unregister a log target from the logging core
|
||||||
|
* \param[in] target Log target to be unregistered
|
||||||
|
*/
|
||||||
void log_del_target(struct log_target *target)
|
void log_del_target(struct log_target *target)
|
||||||
{
|
{
|
||||||
llist_del(&target->entry);
|
llist_del(&target->entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Reset (clear) the logging context */
|
||||||
void log_reset_context(void)
|
void log_reset_context(void)
|
||||||
{
|
{
|
||||||
memset(&log_context, 0, sizeof(log_context));
|
memset(&log_context, 0, sizeof(log_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Set the logging context
|
||||||
|
* \param[in] ctx_nr logging context number
|
||||||
|
* \param[in] value value to which the context is to be set
|
||||||
|
*
|
||||||
|
* A logging context is something like the subscriber identity to which
|
||||||
|
* the currently processed message relates, or the BTS through which it
|
||||||
|
* was received. As soon as this data is known, it can be set using
|
||||||
|
* this function. The main use of context information is for logging
|
||||||
|
* filters.
|
||||||
|
*/
|
||||||
int log_set_context(uint8_t ctx_nr, void *value)
|
int log_set_context(uint8_t ctx_nr, void *value)
|
||||||
{
|
{
|
||||||
if (ctx_nr > LOG_MAX_CTX)
|
if (ctx_nr > LOG_MAX_CTX)
|
||||||
|
@ -337,6 +368,14 @@ int log_set_context(uint8_t ctx_nr, void *value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Enable the \ref LOG_FILTER_ALL log filter
|
||||||
|
* \param[in] target Log target to be affected
|
||||||
|
* \param[in] all enable (1) or disable (0) the ALL filter
|
||||||
|
*
|
||||||
|
* When the \ref LOG_FILTER_ALL filter is enabled, all log messages will
|
||||||
|
* be printed. It acts as a wildcard. Setting it to \a 1 means there
|
||||||
|
* is no filtering.
|
||||||
|
*/
|
||||||
void log_set_all_filter(struct log_target *target, int all)
|
void log_set_all_filter(struct log_target *target, int all)
|
||||||
{
|
{
|
||||||
if (all)
|
if (all)
|
||||||
|
@ -345,16 +384,28 @@ void log_set_all_filter(struct log_target *target, int all)
|
||||||
target->filter_map &= ~LOG_FILTER_ALL;
|
target->filter_map &= ~LOG_FILTER_ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Enable or disable the use of colored output
|
||||||
|
* \param[in] target Log target to be affected
|
||||||
|
* \param[in] use_color Use color (1) or don't use color (0)
|
||||||
|
*/
|
||||||
void log_set_use_color(struct log_target *target, int use_color)
|
void log_set_use_color(struct log_target *target, int use_color)
|
||||||
{
|
{
|
||||||
target->use_color = use_color;
|
target->use_color = use_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Enable or disable printing of timestamps while logging
|
||||||
|
* \param[in] target Log target to be affected
|
||||||
|
* \param[in] print_timestamp Enable (1) or disable (0) timestamps
|
||||||
|
*/
|
||||||
void log_set_print_timestamp(struct log_target *target, int print_timestamp)
|
void log_set_print_timestamp(struct log_target *target, int print_timestamp)
|
||||||
{
|
{
|
||||||
target->print_timestamp = print_timestamp;
|
target->print_timestamp = print_timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Set the global log level for a given log target
|
||||||
|
* \param[in] target Log target to be affected
|
||||||
|
* \param[in] log_level New global log level
|
||||||
|
*/
|
||||||
void log_set_log_level(struct log_target *target, int log_level)
|
void log_set_log_level(struct log_target *target, int log_level)
|
||||||
{
|
{
|
||||||
target->loglevel = log_level;
|
target->loglevel = log_level;
|
||||||
|
@ -376,6 +427,7 @@ static void _file_output(struct log_target *target, unsigned int level,
|
||||||
fflush(target->tgt_file.out);
|
fflush(target->tgt_file.out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Create a new log target skeleton */
|
||||||
struct log_target *log_target_create(void)
|
struct log_target *log_target_create(void)
|
||||||
{
|
{
|
||||||
struct log_target *target;
|
struct log_target *target;
|
||||||
|
@ -411,6 +463,7 @@ struct log_target *log_target_create(void)
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Create the STDERR log target */
|
||||||
struct log_target *log_target_create_stderr(void)
|
struct log_target *log_target_create_stderr(void)
|
||||||
{
|
{
|
||||||
/* since C89/C99 says stderr is a macro, we can safely do this! */
|
/* since C89/C99 says stderr is a macro, we can safely do this! */
|
||||||
|
@ -430,6 +483,10 @@ struct log_target *log_target_create_stderr(void)
|
||||||
#endif /* stderr */
|
#endif /* stderr */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Create a new file-based log target
|
||||||
|
* \param[in] fname File name of the new log file
|
||||||
|
* \returns Log target in case of success, NULL otherwise
|
||||||
|
*/
|
||||||
struct log_target *log_target_create_file(const char *fname)
|
struct log_target *log_target_create_file(const char *fname)
|
||||||
{
|
{
|
||||||
struct log_target *target;
|
struct log_target *target;
|
||||||
|
@ -450,6 +507,11 @@ struct log_target *log_target_create_file(const char *fname)
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Find a registered log target
|
||||||
|
* \param[in] type Log target type
|
||||||
|
* \param[in] fname File name
|
||||||
|
* \returns Log target (if found), NULL otherwise
|
||||||
|
*/
|
||||||
struct log_target *log_target_find(int type, const char *fname)
|
struct log_target *log_target_find(int type, const char *fname)
|
||||||
{
|
{
|
||||||
struct log_target *tgt;
|
struct log_target *tgt;
|
||||||
|
@ -466,6 +528,7 @@ struct log_target *log_target_find(int type, const char *fname)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Unregister, close and delete a log target */
|
||||||
void log_target_destroy(struct log_target *target)
|
void log_target_destroy(struct log_target *target)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -487,7 +550,7 @@ void log_target_destroy(struct log_target *target)
|
||||||
talloc_free(target);
|
talloc_free(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* close and re-open a log file (for log file rotation) */
|
/*! \brief close and re-open a log file (for log file rotation) */
|
||||||
int log_target_file_reopen(struct log_target *target)
|
int log_target_file_reopen(struct log_target *target)
|
||||||
{
|
{
|
||||||
fclose(target->tgt_file.out);
|
fclose(target->tgt_file.out);
|
||||||
|
@ -501,7 +564,9 @@ int log_target_file_reopen(struct log_target *target)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This generates the logging command string for VTY. */
|
/*! \brief Generates the logging command string for VTY
|
||||||
|
* \param[in] unused_info Deprecated parameter, no longer used!
|
||||||
|
*/
|
||||||
const char *log_vty_command_string(const struct log_info *unused_info)
|
const char *log_vty_command_string(const struct log_info *unused_info)
|
||||||
{
|
{
|
||||||
struct log_info *info = osmo_log_info;
|
struct log_info *info = osmo_log_info;
|
||||||
|
@ -576,7 +641,9 @@ err:
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This generates the logging command description for VTY. */
|
/*! \brief Generates the logging command description for VTY
|
||||||
|
* \param[in] unused_info Deprecated parameter, no longer used!
|
||||||
|
*/
|
||||||
const char *log_vty_command_description(const struct log_info *unused_info)
|
const char *log_vty_command_description(const struct log_info *unused_info)
|
||||||
{
|
{
|
||||||
struct log_info *info = osmo_log_info;
|
struct log_info *info = osmo_log_info;
|
||||||
|
@ -634,6 +701,11 @@ err:
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Initialize the Osmocom logging core
|
||||||
|
* \param[in] inf Information regarding logging categories
|
||||||
|
* \param[in] ctx \ref talloc context for logging allocations
|
||||||
|
* \returns 0 in case of success, negative in case of error
|
||||||
|
*/
|
||||||
int log_init(const struct log_info *inf, void *ctx)
|
int log_init(const struct log_info *inf, void *ctx)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -674,3 +746,5 @@ int log_init(const struct log_info *inf, void *ctx)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! }@ */
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*! \addtogroup logging
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*! \file logging_syslog.c */
|
||||||
|
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
#ifdef HAVE_SYSLOG_H
|
#ifdef HAVE_SYSLOG_H
|
||||||
|
@ -57,6 +63,12 @@ static void _syslog_output(struct log_target *target,
|
||||||
syslog(logp2syslog_level(level), "%s", log);
|
syslog(logp2syslog_level(level), "%s", log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Create a new logging target for syslog logging
|
||||||
|
* \param[in] ident syslog string identifier
|
||||||
|
* \param[in] option syslog options
|
||||||
|
* \param[in] facility syslog facility
|
||||||
|
* \returns Log target in case of success, NULL in case of error
|
||||||
|
*/
|
||||||
struct log_target *log_target_create_syslog(const char *ident, int option,
|
struct log_target *log_target_create_syslog(const char *ident, int option,
|
||||||
int facility)
|
int facility)
|
||||||
{
|
{
|
||||||
|
@ -76,3 +88,5 @@ struct log_target *log_target_create_syslog(const char *ident, int option,
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_SYSLOG_H */
|
#endif /* HAVE_SYSLOG_H */
|
||||||
|
|
||||||
|
/* }@ */
|
||||||
|
|
Loading…
Reference in New Issue