From 6bb61d39d4910e3bfb09019426c3b6a8ced5707a Mon Sep 17 00:00:00 2001 From: Krisztian Litkey Date: Fri, 6 Apr 2012 14:04:09 +0300 Subject: [PATCH] common: added a simple logging implementation. --- src/common/log.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/common/log.h | 100 +++++++++++++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 src/common/log.c create mode 100644 src/common/log.h diff --git a/src/common/log.c b/src/common/log.c new file mode 100644 index 0000000..bc14b02 --- /dev/null +++ b/src/common/log.c @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include + +#include + +static int log_mask = MRP_LOG_MASK_ERROR; +static const char *log_target = MRP_LOG_TO_STDERR; +static FILE *log_fp; + + +mrp_log_mask_t mrp_log_parse_levels(const char *levels) +{ + const char *p; + mrp_log_mask_t mask; + + mask = 0; + + if (levels == NULL) { + if (mask == 0) + mask = 1; + else { + mask <<= 1; + mask |= 1; + } + } + else { + p = levels; + while (p && *p) { +# define MATCHES(s, l) (!strcmp(s, l) || \ + !strncmp(s, l",", sizeof(l",") - 1)) + + if (MATCHES(p, "info")) + mask |= MRP_LOG_MASK_INFO; + else if (MATCHES(p, "error")) + mask |= MRP_LOG_MASK_ERROR; + else if (MATCHES(p, "warning")) + mask |= MRP_LOG_MASK_WARNING; + else + return -1; + + if ((p = strchr(p, ',')) != NULL) + p += 1; + +# undef MATCHES + } + } + + return mask; +} + + +const char *mrp_log_parse_target(const char *target) +{ + if (!strcmp(target, "stderr")) + return MRP_LOG_TO_STDERR; + if (!strcmp(target, "stdout")) + return MRP_LOG_TO_STDOUT; + if (!strcmp(target, "syslog")) + return MRP_LOG_TO_SYSLOG; + else + return target; +} + + +mrp_log_mask_t mrp_log_enable(mrp_log_mask_t enabled) +{ + mrp_log_mask_t old_mask = log_mask; + + log_mask |= enabled; + + return old_mask; +} + + +mrp_log_mask_t mrp_log_disable(mrp_log_mask_t disabled) +{ + mrp_log_mask_t old_mask = log_mask; + + log_mask &= ~disabled; + + return old_mask; +} + + +mrp_log_mask_t mrp_log_set_mask(mrp_log_mask_t enabled) +{ + mrp_log_mask_t old_mask = log_mask; + + log_mask = enabled; + + return old_mask; +} + + +int mrp_log_set_target(const char *target) +{ + const char *old_target = log_target; + FILE *old_fp = log_fp; + + if (!target || log_target == target) + return FALSE; + + if (target == MRP_LOG_TO_SYSLOG) { + log_target = target; + log_fp = NULL; + openlog(NULL, 0, LOG_DAEMON); + } + else if (target == MRP_LOG_TO_STDERR) { + log_target = target; + log_fp = stdout; + } + else if (target == MRP_LOG_TO_STDOUT) { + log_target = target; + log_fp = stdout; + } + else { + log_target = target; + log_fp = fopen(log_target, "a"); + + if (log_fp == NULL) { + log_target = old_target; + log_fp = old_fp; + + return FALSE; + } + } + + if (old_target == MRP_LOG_TO_SYSLOG) + closelog(); + else if (old_target != MRP_LOG_TO_STDOUT && old_target != MRP_LOG_TO_STDERR) + fclose(old_fp); + + return TRUE; +} + + +void mrp_log_msg(mrp_log_level_t level, const char *file, + int line, const char *func, const char *format, ...) +{ + va_list ap; + int lvl; + const char *prefix; + char prfx[2*1024]; + + (void)file; + (void)line; + + if (!(log_mask & (1 << level))) + return; + + switch (level) { + case MRP_LOG_ERROR: lvl = LOG_ERR; prefix = "E: "; break; + case MRP_LOG_WARNING: lvl = LOG_WARNING; prefix = "W: "; break; + case MRP_LOG_INFO: lvl = LOG_INFO; prefix = "I: "; break; + case MRP_LOG_DEBUG: lvl = LOG_INFO; + snprintf(prfx, sizeof(prfx) - 1, "D: [%s] ", func); + prfx[sizeof(prfx)-1] = '\0'; + prefix = prfx; + break; + default: + return; + } + + va_start(ap, format); + + if (log_fp == NULL) + vsyslog(lvl, format, ap); + else { + fputs(prefix, log_fp); + vfprintf(log_fp, format, ap); fputs("\n", log_fp); + fflush(log_fp); + } + + va_end(ap); +} + + +/* + * workaround for not being able to initialize log_fp to stderr + */ + +static __attribute__((constructor)) void set_default_logging(void) +{ + log_target = MRP_LOG_TO_STDERR; + log_fp = stderr; +} diff --git a/src/common/log.h b/src/common/log.h new file mode 100644 index 0000000..b03e75a --- /dev/null +++ b/src/common/log.h @@ -0,0 +1,100 @@ +#ifndef __MURPHY_LOG_H__ +#define __MURPHY_LOG_H__ + +/** \file + * Logging functions and macros. + */ + +#include + +#include + +MRP_CDECL_BEGIN + +#define MRP_LOG_NAME_ERROR "error" /**< name for error level */ +#define MRP_LOG_NAME_WARNING "warning" /**< name for warning level */ +#define MRP_LOG_NAME_INFO "info" /**< name for info level */ +#define MRP_LOG_NAME_DEBUG "debug" /**< name for debug level */ + + +/** + * Logging levels. + */ +typedef enum { + MRP_LOG_ERROR = 0, /**< error log level */ + MRP_LOG_WARNING, /**< warning log level */ + MRP_LOG_INFO, /**< info log level */ + MRP_LOG_DEBUG, /**< debug log level */ +} mrp_log_level_t; + + +/** + * Logging masks. + */ +typedef enum { + MRP_LOG_MASK_ERROR = 0x01, /**< error logging mask */ + MRP_LOG_MASK_WARNING = 0x02, /**< warning logging mask */ + MRP_LOG_MASK_INFO = 0x04, /**< info logging mask */ + MRP_LOG_MASK_DEBUG = 0x08, /**< debug logging mask */ +} mrp_log_mask_t; + +#define MRP_LOG_MASK(level) (1 << ((level) - 1)) /**< mask of level */ +#define MRP_LOG_UPTO(level) ((1 << (level)) - 1) /**< mask up to level */ + +/** Parse a string of comma-separated log level names to a log mask. */ +mrp_log_mask_t mrp_log_parse_levels(const char *levels); + +/** Clear current logging level and enable levels in mask. */ +mrp_log_mask_t mrp_log_set_mask(mrp_log_mask_t mask); + +/** Enable logging for levels in mask. */ +mrp_log_mask_t mrp_log_enable(mrp_log_mask_t mask); + +/** Disable logging for levels in mask. */ +mrp_log_mask_t mrp_log_disable(mrp_log_mask_t mask); + +/** + * Logging target names. + */ +#define MRP_LOG_NAME_STDOUT "stdout" +#define MRP_LOG_NAME_STDERR "stderr" +#define MRP_LOG_NAME_SYSLOG "syslog" + +/** + * Logging targets. + */ +#define MRP_LOG_TO_STDOUT ((const char *)1) +#define MRP_LOG_TO_STDERR ((const char *)2) +#define MRP_LOG_TO_SYSLOG ((const char *)3) +#define MRP_LOG_TO_FILE(path) ((const char *)(path)) + +/** Parse a log target name to MRP_LOG_TO_*. */ +const char *mrp_log_parse_target(const char *target); + +/** Set logging target. */ +int mrp_log_set_target(const char *target); + +/** Log an error. */ +#define mrp_log_error(fmt, args...) \ + mrp_log_msg(MRP_LOG_ERROR, __LOC__, fmt , ## args) + +/** Log a warning. */ +#define mrp_log_warning(fmt, args...) \ + mrp_log_msg(MRP_LOG_WARNING, __LOC__, fmt , ## args) + +/** Log an informational message. */ +#define mrp_log_info(fmt, args...) \ + mrp_log_msg(MRP_LOG_INFO, __LOC__, fmt , ## args) + +/** Log an (unclassified) debugging message. */ +#define mrp_debug(fmt, args...) \ + mrp_log_msg(MRP_LOG_DEBUG, __LOC__, fmt , ## args) + +/** Generic logging function. */ +void mrp_log_msg(mrp_log_level_t level, + const char *file, int line, const char *func, + const char *format, ...) MRP_PRINTF_LIKE(5, 6); + +MRP_CDECL_END + +#endif /* __MURPHY_LOG_H__ */ -- 2.7.4