#ifndef UCORE_LOGGING_H_ #define UCORE_LOGGING_H_ /** Logging functions. * All logging functions except uc_log_init are thread safe, * so logging can be performed from any thread after the logging * system have been initialized. * * The logging system has the concept of 'modules'. Modules are defined * by the application, and would match the logical parts of an application. * uc_log_init() tells the logging library about these modules, and would normally * be used like: * * enum { * POLLER, * DB, * IO *}; * * struct uc_log_module modules[] = { * { * .id = POLLER, * .short_name = "POLLER", * .long_name = "Poller thread", * .log_level = UC_LL_DEBUG, * }, * { * .id = DB, * .short_name = "DB", * .long_name = "Database handler", * .log_level == UC_LL_DEBUG * }, * { * .id = IO, * .short_name = "IO", * .long_name = "I/O worker", * .log_level == UC_LL_DEBUG * } * }; * struct uc_log_modules m = { * .mods = modules, * .cnt = ARRAY_SIZE(modules) * }; * * uc_log_init(&m); * * So the application defines 3 modules logging * will be categorized by. * Note that the values (the enum in this case) * defining all the .id memmbers of uc_log_module * must start at 0 and be concecutive. * * Now, the database code in the application can do * logging as e.g. * * UC_LOGF(UC_LL_INFO, DB, "connecting to server %s\n", ip); * * And the resulting log line will include the short_name * modules[DB].short_name * */ #ifdef __cplusplus extern "C" { #endif /** The log levels defined by ucore logging*/ enum UC_LOG_LEVEL { UC_LL_NONE = 0, UC_LL_DEBUG = 1, UC_LL_INFO = 3, UC_LL_WARNING = 5, UC_LL_ERROR = 7, }; /** A destination for the logging messages*/ enum UC_LOG_DESTINATION { /** Logs using the unix syslog system */ UC_LDEST_SYSLOG, /** Prints log messages to stderr. */ UC_LDEST_STDERR, /** Prints log messages to a file */ UC_LDEST_FILE, }; /** A module of a program, that will perform logging. * This is used group logging from parts of a larger program, * and allow the log message to identigy which module the * log message originates from */ struct uc_log_module { /** The id of the log module. * This is the id one specifies in the various log * functions/macros*/ int id; /** A short name for the module. * This will appear in log messages */ const char *short_name; /** A longer description for the log module*/ const char *long_name; /** The log level of this module. Only * log statements with a level >= the log_level * are actually logged */ int log_level; }; /* A collection of struct uc_log_module */ struct uc_log_modules { /* Pointer to the first element of the array */ struct uc_log_module *mods; /** The number of elements in the mods array. */ int cnt; }; struct uc_log_destination; /* Returns a string representation of the log level. * * @param ll The log level * @return String representation of the log level. (This will be a string literal) */ const char *uc_ll_2_str(enum UC_LOG_LEVEL l); /* creates a new uc_log_destination for printing on stderr. * * @param log_level log level of this destination. only log messages * with a log level >= the log level of the destination are actually logged. * @param log_location whether to log info about the source file and line number * in a log message. * * @return An opaque uc_log_destination that can be added as a destination to * the ucore logging system */ struct uc_log_destination *uc_log_new_stderr(int log_level, int log_location); /* creates a new uc_log_destination for logging to syslog * * @param ident The ident as used in the syslog openlog() funcion * @param facility The facility as used in the syslog openlog() function() * @param log_level log level of this destination. only log messages * with a log level >= the log level of the destination are actually logged. * @param log_location whether to log info about the source file and line number * in a log message. * @return An opaque uc_log_destination that can be added as a destination to * the ucore logging system */ struct uc_log_destination *uc_log_new_syslog(const char *ident, int facility, int log_level, int log_location); /* creates a new uc_log_destination for printing on stderr. * * @param log_level log level of this destination. only log messages * with a log level >= the log level of the destination are actually logged. * @param log_location whether to log info about the source file and line number * in a log message. * @param return An opaque uc_log_destination that can be added as a destination to * the ucore logging system */ struct uc_log_destination *uc_log_new_file(const char *filename, int log_level, int log_location); /** Add a uc_log_destination to the logging system. * * @param dest The uc_log_destination to add. */ void uc_log_add_destination(struct uc_log_destination *dest); /** Remove a log destination. * Note that this does not free the destination, it can be readded later. * For file destination, the log file is NOT closed. * * @param dest The uc_log_destination to remove. */ void uc_log_remove_destination(struct uc_log_destination *dest); /** Remove and free a destination. * This frees the memory allocated to the destination. For * UC_LDEST_FILE the log file is closed. * * If the destination is not already removed, it will be removed first, * there's no need to call uc_log_remove_destination first. * The destination cannot be used again after this function has been called. * * @param dest The destination to delete. */ void uc_log_delete_destination(struct uc_log_destination *dest); /** Change the log level of a module. * * @param module The module to change, matched against the id member of a struct uc_log_module * @param level The log level for this module * * @return 0 on success, non-zero if the module was not found. */ int uc_log_module_set_loglevel(int module, enum UC_LOG_LEVEL level); /** Closes and re-opens all the UC_LDEST_FILE log destinations. * Intended for use when a log file is rotated externally. * * @param return 0 on success, non-zero if an error occured when re-opening a file. */ int uc_log_reopen_files(void); /** Init the logging system. This function must be called before performing any other * logging action. * * @param user_struct containing an array of all the modules defined by the application. */ void uc_log_init(struct uc_log_modules *user_modules); void uc_logf(int log_level, int module, int raw, const char *file, int line, const char *fmt, ...) __attribute__((format(printf, 6, 7))); #ifdef DEBUG # define UC_DEBUGF(mod, fmt, ...)\ uc_logf(UC_LL_DEBUG, mod,0 , __FILE__, __LINE__, fmt, ## __VA_ARGS__) # define UC_DEBUGFR(mod, fmt, ...)\ uc_logf(UC_LL_DEBUG, mod,1 , , __LINE__, fmt, ## __VA_ARGS__) #else # define UC_DEBUGF(mod, fmt, ...) # define UC_DEBUGFR(mod, fmt, ...) #endif /** Main macro that should be used for logging. * * For log messages with UC_LL_DEBUG, the UC_DEBUGF() macro can be used, * UC_DEBUGF will only be compiled in if the DEBUG macro is defined * * @param lvl log level of this log message * @param mod module id of this log messagex. * @param fmt printf style format string * @param ... printf style arguments */ #define UC_LOGF(lvl, mod, fmt, ...) \ uc_logf(lvl, mod, 0, __FILE__, __LINE__, fmt, ## __VA_ARGS__) /** Raw logging ,Like UC_LOGF, but only prints the supplied * data, not timestamp, log level etc. */ #define UC_LOGFR(lvl, mod, fmt, ...) \ uc_logf(lvl, mod, 1, __FILE__, __LINE__, fmt, ## __VA_ARGS__) #ifdef __cplusplus } #endif #endif