char *buf, size_t buflen);
static INLINE char *format_msg(char *buf, size_t buf_len,
log_domain_mask_t domain, int severity, const char *funcname,
+ const char *suffix,
const char *format, va_list ap, size_t *msg_len_out)
- CHECK_PRINTF(6,0);
+ CHECK_PRINTF(7,0);
static void logv(int severity, log_domain_mask_t domain, const char *funcname,
- const char *format, va_list ap)
- CHECK_PRINTF(4,0);
+ const char *suffix, const char *format, va_list ap)
+ CHECK_PRINTF(5,0);
/** Name of the application: used to generate the message we write at the
* start of each new log. */
static INLINE char *
format_msg(char *buf, size_t buf_len,
log_domain_mask_t domain, int severity, const char *funcname,
+ const char *suffix,
const char *format, va_list ap, size_t *msg_len_out)
{
size_t n;
n = buf_len;
} else {
n += r;
+ if (suffix) {
+ size_t suffix_len = strlen(suffix);
+ if (buf_len-n >= suffix_len) {
+ memcpy(buf+n, suffix, suffix_len);
+ n += suffix_len;
+ }
+ }
}
buf[n]='\n';
buf[n+1]='\0';
*/
static void
logv(int severity, log_domain_mask_t domain, const char *funcname,
- const char *format, va_list ap)
+ const char *suffix, const char *format, va_list ap)
{
char buf[10024];
size_t msg_len = 0;
if (!formatted) {
end_of_prefix =
- format_msg(buf, sizeof(buf), domain, severity, funcname, format, ap,
- &msg_len);
+ format_msg(buf, sizeof(buf), domain, severity, funcname, suffix,
+ format, ap, &msg_len);
formatted = 1;
}
if (severity > log_global_min_severity_)
return;
va_start(ap,format);
- logv(severity, domain, NULL, format, ap);
+ logv(severity, domain, NULL, NULL, format, ap);
va_end(ap);
}
if (severity > log_global_min_severity_)
return;
va_start(ap,format);
- logv(severity, domain, fn, format, ap);
+ logv(severity, domain, fn, NULL, format, ap);
+ va_end(ap);
+}
+void
+log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
+ const char *fn, const char *format, ...)
+{
+ va_list ap;
+ char *m;
+ if (severity > log_global_min_severity_)
+ return;
+ m = rate_limit_log(ratelim, approx_time());
+ if (m == NULL)
+ return;
+ va_start(ap, format);
+ logv(severity, domain, fn, m, format, ap);
va_end(ap);
+ tor_free(m);
}
#else
/** @{ */
if (severity > log_global_min_severity_)
return;
va_start(ap,format);
- logv(severity, domain, log_fn_function_name_, format, ap);
+ logv(severity, domain, log_fn_function_name_, NULL, format, ap);
va_end(ap);
log_fn_function_name_ = NULL;
}
void
+log_fn_ratelim_(ratelim_t *ratelim, int severity, log_domain_mask_t domain,
+ const char *format, ...)
+{
+ va_list ap;
+ char *m;
+ if (severity > log_global_min_severity_)
+ return;
+ m = rate_limit_log(ratelim, approx_time());
+ if (m == NULL)
+ return;
+ va_start(ap, format);
+ logv(severity, domain, log_fn_function_name_, m, format, ap);
+ va_end(ap);
+ tor_free(m);
+}
+void
log_debug_(log_domain_mask_t domain, const char *format, ...)
{
va_list ap;
if (PREDICT_LIKELY(LOG_DEBUG > log_global_min_severity_))
return;
va_start(ap,format);
- logv(LOG_DEBUG, domain, log_fn_function_name_, format, ap);
+ logv(LOG_DEBUG, domain, log_fn_function_name_, NULL, format, ap);
va_end(ap);
log_fn_function_name_ = NULL;
}
if (LOG_INFO > log_global_min_severity_)
return;
va_start(ap,format);
- logv(LOG_INFO, domain, log_fn_function_name_, format, ap);
+ logv(LOG_INFO, domain, log_fn_function_name_, NULL, format, ap);
va_end(ap);
log_fn_function_name_ = NULL;
}
if (LOG_NOTICE > log_global_min_severity_)
return;
va_start(ap,format);
- logv(LOG_NOTICE, domain, log_fn_function_name_, format, ap);
+ logv(LOG_NOTICE, domain, log_fn_function_name_, NULL, format, ap);
va_end(ap);
log_fn_function_name_ = NULL;
}
if (LOG_WARN > log_global_min_severity_)
return;
va_start(ap,format);
- logv(LOG_WARN, domain, log_fn_function_name_, format, ap);
+ logv(LOG_WARN, domain, log_fn_function_name_, NULL, format, ap);
va_end(ap);
log_fn_function_name_ = NULL;
}
if (LOG_ERR > log_global_min_severity_)
return;
va_start(ap,format);
- logv(LOG_ERR, domain, log_fn_function_name_, format, ap);
+ logv(LOG_ERR, domain, log_fn_function_name_, NULL, format, ap);
va_end(ap);
log_fn_function_name_ = NULL;
}
void log_fn_(int severity, log_domain_mask_t domain,
const char *funcname, const char *format, ...)
CHECK_PRINTF(4,5);
+struct ratelim_t;
+void log_fn_ratelim_(struct ratelim_t *ratelim, int severity,
+ log_domain_mask_t domain, const char *funcname,
+ const char *format, ...)
+ CHECK_PRINTF(5,6);
/** Log a message at level <b>severity</b>, using a pretty-printed version
* of the current function name. */
#define log_fn(severity, domain, args...) \
log_fn_(severity, domain, __PRETTY_FUNCTION__, args)
+/** As log_fn, but use <b>ratelim</b> (an instance of ratelim_t) to control
+ * the frequency at which messages can appear.
+ */
+#define log_fn_ratelim(ratelim, severity, domain, args...) \
+ log_fn_ratelim_(ratelim, severity, domain, __PRETTY_FUNCTION__, args)
#define log_debug(domain, args...) \
STMT_BEGIN \
if (PREDICT_UNLIKELY(log_global_min_severity_ == LOG_DEBUG)) \
#else /* ! defined(__GNUC__) */
void log_fn_(int severity, log_domain_mask_t domain, const char *format, ...);
+struct ratelim_t;
+void log_fn_ratelim_(struct ratelim_t *ratelim, int severity,
+ log_domain_mask_t domain, const char *format, ...);
void log_debug_(log_domain_mask_t domain, const char *format, ...);
void log_info_(log_domain_mask_t domain, const char *format, ...);
void log_notice_(log_domain_mask_t domain, const char *format, ...);
#if defined(_MSC_VER) && _MSC_VER < 1300
/* MSVC 6 and earlier don't have __func__, or even __LINE__. */
#define log_fn log_fn_
+#define log_fn_ratelim log_fn_ratelim_
#define log_debug log_debug_
#define log_info log_info_
#define log_notice log_notice_
* do {...} while (0) trick to wrap this macro, since the macro can't take
* arguments. */
#define log_fn (log_fn_function_name_=__func__),log_fn_
+#define log_fn_ratelim (log_fn_function_name_=__func__),log_fn_ratelim_
#define log_debug (log_fn_function_name_=__func__),log_debug_
#define log_info (log_fn_function_name_=__func__),log_info_
#define log_notice (log_fn_function_name_=__func__),log_notice_