X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fvlog.c;h=a136e5634902e981461d3fc6fd93f7bae049ba04;hb=a846b3519b004f95d2b3ab0aabd756f27f8c881d;hp=6e098ef964ec8c1a9b254ebfbd403e793995101e;hpb=f12a5936173a7182fec670b2891137fc66adc929;p=sliver-openvswitch.git diff --git a/lib/vlog.c b/lib/vlog.c index 6e098ef96..a136e5634 100644 --- a/lib/vlog.c +++ b/lib/vlog.c @@ -43,29 +43,30 @@ #include #include #include "dynamic-string.h" +#include "sat-math.h" +#include "timeval.h" #include "util.h" #define THIS_MODULE VLM_vlog /* Name for each logging level. */ static const char *level_names[VLL_N_LEVELS] = { - [VLL_EMER] = "EMER", - [VLL_ERR] = "ERR", - [VLL_WARN] = "WARN", - [VLL_DBG] = "DBG", +#define VLOG_LEVEL(NAME) #NAME, + VLOG_LEVELS +#undef VLOG_LEVEL }; /* Name for each logging facility. */ static const char *facility_names[VLF_N_FACILITIES] = { - [VLF_CONSOLE] = "console", - [VLF_SYSLOG] = "syslog", +#define VLOG_FACILITY(NAME) #NAME, + VLOG_FACILITIES +#undef VLOG_FACILITY }; /* Name for each logging module */ static const char *module_names[VLM_N_MODULES] = { #define VLOG_MODULE(NAME) #NAME, - VLOG_MODULES -#undef VLOG_MODULES +#include "vlog-modules.def" }; static int levels[VLM_N_MODULES][VLF_N_FACILITIES]; @@ -239,7 +240,7 @@ vlog_set_verbosity(const char *arg) if (arg) { char *msg = vlog_set_levels_from_string(arg); if (msg) { - fatal(0, "processing \"%s\": %s", arg, msg); + ofp_fatal(0, "processing \"%s\": %s", arg, msg); } } else { vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG); @@ -255,7 +256,7 @@ vlog_init(void) openlog(program_name, LOG_NDELAY, LOG_DAEMON); vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_WARN); - now = time(0); + now = time_now(); if (now < 0) { struct tm tm; char s[128]; @@ -308,7 +309,8 @@ vlog_is_enabled(enum vlog_module module, enum vlog_level level) * * Guaranteed to preserve errno. */ void -vlog(enum vlog_module module, enum vlog_level level, const char *message, ...) +vlog_valist(enum vlog_module module, enum vlog_level level, + const char *message, va_list args) { bool log_console = levels[module][VLF_CONSOLE] >= level; bool log_syslog = levels[module][VLF_SYSLOG] >= level; @@ -319,45 +321,98 @@ vlog(enum vlog_module module, enum vlog_level level, const char *message, ...) const char *level_name = vlog_get_level_name(level); time_t now; struct tm tm; - va_list args; - char s[1024]; - size_t len, time_len; + size_t time_len; + struct ds s; - now = time(0); + now = time_now(); localtime_r(&now, &tm); - len = time_len = strftime(s, sizeof s, "%b %d %H:%M:%S|", &tm); - len += sprintf(s + len, "%05d|%s|%s:", - ++msg_num, module_name, level_name); - va_start(args, message); - len += vsnprintf(s + len, sizeof s - len, message, args); - va_end(args); - if (len >= sizeof s) { - len = sizeof s; - } - if (s[len - 1] == '\n') { - s[len - 1] = '\0'; - } + /* Compose log message. */ + ds_init(&s); + ds_reserve(&s, 1024); + ds_put_strftime(&s, "%b %d %H:%M:%S|", &tm); + time_len = s.length; + ds_put_format(&s, "%05d|%s|%s:", ++msg_num, module_name, level_name); + ds_put_format_valist(&s, message, args); + ds_chomp(&s, '\n'); if (log_console) { - fprintf(stderr, "%s\n", s); + fprintf(stderr, "%s\n", s.string); } if (log_syslog) { - static const int syslog_levels[VLL_N_LEVELS] = { - [VLL_EMER] = LOG_ALERT, - [VLL_ERR] = LOG_ERR, - [VLL_WARN] = LOG_WARNING, - [VLL_DBG] = LOG_DEBUG, - }; + int syslog_level = LOG_ALERT; char *save_ptr = NULL; char *line; - for (line = strtok_r(s + time_len, "\n", &save_ptr); line != NULL; + switch (level) { + case VLL_EMER: syslog_level = LOG_ALERT; break; + case VLL_ERR: syslog_level = LOG_ERR; break; + case VLL_WARN: syslog_level = LOG_WARNING; break; + case VLL_DBG: syslog_level = LOG_DEBUG; break; + case VLL_N_LEVELS: NOT_REACHED(); + } + for (line = strtok_r(&s.string[time_len], "\n", &save_ptr); line; line = strtok_r(NULL, "\n", &save_ptr)) { - syslog(syslog_levels[level], "%s", line); + syslog(syslog_level, "%s", line); } } + + ds_destroy(&s); errno = save_errno; } } + +void +vlog(enum vlog_module module, enum vlog_level level, const char *message, ...) +{ + va_list args; + + va_start(args, message); + vlog_valist(module, level, message, args); + va_end(args); +} + +void +vlog_rate_limit(enum vlog_module module, enum vlog_level level, + struct vlog_rate_limit *rl, const char *message, ...) +{ + va_list args; + + if (!vlog_is_enabled(module, level)) { + return; + } + + if (rl->tokens < VLOG_MSG_TOKENS) { + time_t now = time_now(); + if (rl->last_fill > now) { + /* Last filled in the future? Time must have gone backward, or + * 'rl' has not been used before. */ + rl->tokens = rl->burst; + } else if (rl->last_fill < now) { + unsigned int add = sat_mul(rl->rate, now - rl->last_fill); + unsigned int tokens = sat_add(rl->tokens, add); + rl->tokens = MIN(tokens, rl->burst); + rl->last_fill = now; + } + if (rl->tokens < VLOG_MSG_TOKENS) { + if (!rl->n_dropped) { + rl->first_dropped = now; + } + rl->n_dropped++; + return; + } + } + rl->tokens -= VLOG_MSG_TOKENS; + + va_start(args, message); + vlog_valist(module, level, message, args); + va_end(args); + + if (rl->n_dropped) { + vlog(module, level, + "Dropped %u messages in last %u seconds due to excessive rate", + rl->n_dropped, (unsigned int) (time_now() - rl->first_dropped)); + rl->n_dropped = 0; + } +}