From e305c764722394c18d55e084c7be4b64ff799fa4 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 4 Oct 2011 11:09:39 +0000 Subject: LRN's big logging rewrite (#1805): * GNUNET_BOTTOM_LOGLEVEL and GNUNET_TOP_LOGLEVEL set global levels Use bottom level to force logging to be more verbose than configured Use top level to force logging to be less verbose than configured Obviously, bottom <= top * GNUNET_LOG sets per-component levels GNUNET_LOG looks like this: name[/bottom[/top]]/... name starts with a non-digit character, must not include '/' bottom and top must consist only of digits, or be empty a description is only used if it matches the component exactly as a special exception (for now) the name '*' matches any component per-component loglevels override global loglevels global levels override whatever is given via arguments or in config Examples: test_client/8/8/ run test_client with DEBUG level (usually leads to a timeout, by the way) */2/2/core/8/8/transport/4/4 run everything with WARNING, core - with DEBUG, transport - with INFO *//1/peerinfo/4/ run everything with top loglevel ERROR, global/configured bottom loglevel, and peerinfo - with bottom loglevel INFO and global/configured top loglevel statistics/ does nothing * Added GNUNET_ERROR_TYPE_UNSPECIFIED enum value, to hold -1. Its corresponding string is NULL. * Changed the logger calls as Grothoff suggested - to use static int to hold the result of runtime evaluation of logability. Logging can be unconditionally disabled in advance by defining GNUNET_LOG_CALL_STATUS to 0, and enabled in advance by defining it to 1. * Added GNUNET_CULL_LOGGING, which, if defined, completely culls out all logging calls at compile time. * Log definition parsing is only done once, results are cached. * Changed definition format, now it looks like this: [component|*|];[file|*|];[function|*|];[from_line[-to_line]];level/[component...] All field separators are mandatory (but some fields could be empty or be '*'). Line definition must be either empty or "number" or "number-number" Level definition must not be empty, and is a string representation of the level (i.e. DEBUG, WARNING, INFO, etc). Definition entry must end with a slash, whether or not there's another entry after it. File name is matched to the end of __FILE__, which allows file name to match not only the base name, but also directories leading to it. * Removed default WARNING loglevel from program and service utility code. Now they default to NULL (UNSPECIFIED) level, which can be overriden by GNUNET_LOG definition, if no level is specified via config or commandline. Log levels from config or commandline are overriden by GNUNET_FORCE_LOG. If GNUNET_*LOG are undefined, and no levels came from config or commandline, logger internally defaults to WARNING level. Add --enable-logging configure option --- src/include/gnunet_common.h | 62 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) (limited to 'src/include') diff --git a/src/include/gnunet_common.h b/src/include/gnunet_common.h index f4844821c..6b3ffe2af 100644 --- a/src/include/gnunet_common.h +++ b/src/include/gnunet_common.h @@ -138,6 +138,7 @@ typedef int (*GNUNET_FileNameCallback) (void *cls, const char *filename); */ enum GNUNET_ErrorType { + GNUNET_ERROR_TYPE_UNSPECIFIED = -1, GNUNET_ERROR_TYPE_NONE = 0, GNUNET_ERROR_TYPE_ERROR = 1, GNUNET_ERROR_TYPE_WARNING = 2, @@ -161,6 +162,15 @@ typedef void (*GNUNET_Logger) (void *cls, enum GNUNET_ErrorType kind, const char *component, const char *date, const char *message); + +/** + * Number of log calls to ignore. + */ +extern unsigned int skip_log; +#if !defined(GNUNET_CULL_LOGGING) +int +GNUNET_get_log_call_status (int caller_level, const char *comp, const char *file, const char *function, int line); +#endif /** * Main log function. * @@ -169,9 +179,29 @@ typedef void (*GNUNET_Logger) (void *cls, enum GNUNET_ErrorType kind, * @param ... arguments for format string */ void -GNUNET_log (enum GNUNET_ErrorType kind, const char *message, ...); - +GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...); + +/* from glib */ +#if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) +#define _GNUNET_BOOLEAN_EXPR(expr) \ + __extension__ ({ \ + int _gnunet_boolean_var_; \ + if (expr) \ + _gnunet_boolean_var_ = 1; \ + else \ + _gnunet_boolean_var_ = 0; \ + _gnunet_boolean_var_; \ +}) +#define GN_LIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 1)) +#define GN_UNLIKELY(expr) (__builtin_expect (_GNUNET_BOOLEAN_EXPR(expr), 0)) +#else +#define GN_LIKELY(expr) (expr) +#define GN_UNLIKELY(expr) (expr) +#endif +#if !defined(GNUNET_LOG_CALL_STATUS) +#define GNUNET_LOG_CALL_STATUS -1 +#endif /** * Log function that specifies an alternative component. @@ -183,9 +213,35 @@ GNUNET_log (enum GNUNET_ErrorType kind, const char *message, ...); * @param ... arguments for format string */ void -GNUNET_log_from (enum GNUNET_ErrorType kind, const char *comp, +GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp, const char *message, ...); +#if !defined(GNUNET_CULL_LOGGING) +#define GNUNET_log_from(kind,comp,...) do { int log_line = __LINE__;\ + static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\ + if (GN_UNLIKELY(log_call_enabled == -1))\ + log_call_enabled = GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), comp, __FILE__, __FUNCTION__, log_line);\ + if (GN_UNLIKELY(skip_log > 0)) {skip_log--;}\ + else {\ + if (GN_UNLIKELY(log_call_enabled))\ + GNUNET_log_from_nocheck (kind, comp, __VA_ARGS__);\ + }\ +} while (0) + +#define GNUNET_log(kind,...) do { int log_line = __LINE__;\ + static int log_call_enabled = GNUNET_LOG_CALL_STATUS;\ + if (GN_UNLIKELY(log_call_enabled == -1))\ + log_call_enabled = GNUNET_get_log_call_status ((kind) & (~GNUNET_ERROR_TYPE_BULK), NULL, __FILE__, __FUNCTION__, log_line);\ + if (GN_UNLIKELY(skip_log > 0)) {skip_log--;}\ + else {\ + if (GN_UNLIKELY(log_call_enabled))\ + GNUNET_log_nocheck (kind, __VA_ARGS__);\ + }\ +} while (0) +#else +#define GNUNET_log(...) +#define GNUNET_log_from(...) +#endif /** * Ignore the next n calls to the log function. -- cgit v1.2.3