doxygen documentation for logging framework

This commit is contained in:
Harald Welte 2011-08-17 14:14:17 +02:00
parent ba6988bd89
commit 18fc465b7f
3 changed files with 137 additions and 30 deletions

View File

@ -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 */

View File

@ -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;
} }
/*! }@ */

View File

@ -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 */
/* }@ */