Improve handling of verbosity
authorJosé Bollo <jose.bollo@iot.bzh>
Mon, 4 Sep 2017 12:40:14 +0000 (14:40 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Thu, 7 Sep 2017 07:43:13 +0000 (09:43 +0200)
The macros VERBOSE_NO_DATA and VERBOSE_NO_DETAILS can
be used to tune what verbose parts are to be emitted:

If VERBOSE_NO_DATA is defined then the macro will only
report the file and the line that emitted the message.
This mode is intended to reduce the count of static data
in the binary.

If VERBOSE_NO_DATA is not defined and VERBOSE_NO_DETAILS
is defined, this is the opposite: the messages are emitted
but not the file, line and function.

When none of these 2 are difened, everything is emitted:
the message and the details (file, line and function).

At the same time the emission of the details (file, line,
function) is not done for levels NOTICE, INFO, DEBUG on
the console

Change-Id: Ibb83cd435797fadf90626cb06bbda77f0f8b3cde
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
src/afb-hook.c
src/verbose.c
src/verbose.h

index c2baf47..7dd81cb 100644 (file)
@@ -1415,7 +1415,7 @@ static struct afb_hook_global_itf hook_global_default_itf = {
 
 static void afb_hook_global_vverbose(int level, const char *file, int line, const char *func, const char *fmt, va_list args)
 {
-       _HOOK_GLOBAL_(vverbose, level, file ?: "?", line, func ?: "?", fmt, args);
+       _HOOK_GLOBAL_(vverbose, level, file ?: "?", line, func ?: "?", fmt ?: "", args);
 }
 
 /******************************************************************************
index e0e3824..b875106 100644 (file)
@@ -83,6 +83,8 @@ void verbose_set_name(const char *name, int authority)
 
 #include <unistd.h>
 #include <errno.h>
+#include <string.h>
+#include <sys/uio.h>
 
 static const char *appname;
 
@@ -99,18 +101,76 @@ static const char *prefixes[] = {
        "<7> DEBUG"
 };
 
+static int tty;
+
+static const char chars[] = { '\n', '?', ':', ' ', '[', ',', ']' };
+
 static void _vverbose_(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args)
 {
-       int saverr = errno;
-       int tty = isatty(fileno(stderr));
-       errno = saverr;
+       char buffer[4000];
+       char lino[40];
+       int saverr, n, rc;
+       struct iovec iov[20];
+
+       saverr = errno;
+
+       if (!tty)
+               tty = 1 + isatty(STDERR_FILENO);
+
+       iov[0].iov_base = (void*)prefixes[CROP_LOGLEVEL(loglevel)] + (tty - 1 ? 4 : 0);
+       iov[0].iov_len = strlen(iov[0].iov_base);
+
+       iov[1].iov_base = (void*)&chars[2];
+       iov[1].iov_len = 2;
+
+       n = 2;
+       if (fmt) {
+               iov[n].iov_base = buffer;
+               rc = vsnprintf(buffer, sizeof buffer, fmt, args);
+               if (rc < 0)
+                       rc = 0;
+               else if ((size_t)rc > sizeof buffer) {
+                       rc = (int)sizeof buffer;
+                       buffer[rc - 1] = buffer[rc - 2]  = buffer[rc - 3] = '.';
+               }
+               iov[n++].iov_len = (size_t)rc;
+       }
+       if (file && (!fmt || tty == 1 || loglevel <= Log_Level_Warning)) {
+               iov[n].iov_base = (void*)&chars[3 + !fmt];
+               iov[n++].iov_len = 2 - !fmt;
+               iov[n].iov_base = (void*)file;
+               iov[n++].iov_len = strlen(file);
+               iov[n].iov_base = (void*)&chars[2];
+               iov[n++].iov_len = 1;
+               if (line) {
+                       iov[n].iov_base = lino;
+                       iov[n++].iov_len = snprintf(lino, sizeof lino, "%d", line);
+               } else {
+                       iov[n].iov_base = (void*)&chars[1];
+                       iov[n++].iov_len = 1;
+               }
+               iov[n].iov_base = (void*)&chars[5];
+               iov[n++].iov_len = 1;
+               if (function) {
+                       iov[n].iov_base = (void*)function;
+                       iov[n++].iov_len = strlen(function);
+               } else {
+                       iov[n].iov_base = (void*)&chars[1];
+                       iov[n++].iov_len = 1;
+               }
+               iov[n].iov_base = (void*)&chars[6];
+               iov[n++].iov_len = 1;
+       }
+       if (n == 2) {
+               iov[n].iov_base = (void*)&chars[1];
+               iov[n++].iov_len = 1;
+       }
+       iov[n].iov_base = (void*)&chars[0];
+       iov[n++].iov_len = 1;
 
-       fprintf(stderr, "%s: ", prefixes[CROP_LOGLEVEL(loglevel)] + (tty ? 4 : 0));
-       vfprintf(stderr, fmt, args);
-       if (file != NULL && (!tty || verbosity > 2))
-               fprintf(stderr, " [%s:%d,%s]\n", file, line, function);
-       else
-               fprintf(stderr, "\n");
+       writev(STDERR_FILENO, iov, n);
+
+       errno = saverr;
 }
 
 void verbose_set_name(const char *name, int authority)
index 4b103ca..402da40 100644 (file)
@@ -73,12 +73,23 @@ enum log_levels
 extern void verbose(int loglevel, const char *file, int line, const char *function, const char *fmt, ...) __attribute__((format(printf, 5, 6)));
 extern void vverbose(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args);
 
-# define _VERBOSE_(vlvl,llvl,...)  do{ if (verbosity >= vlvl) verbose(llvl, __FILE__, __LINE__, __func__, __VA_ARGS__); } while(0)
+#if defined(VERBOSE_NO_DATA)
+# define __VERBOSE__(lvl,...)      do{if((lvl)<=Log_Level_Error) verbose(lvl, __FILE__, __LINE__, __func__, __VA_ARGS__)\
+                                       else verbose(lvl, __FILE__, __LINE__, __func__, NULL);}while(0)
+#elif defined(VERBOSE_NO_DETAILS)
+# define __VERBOSE__(lvl,...)      verbose(lvl, NULL, 0, NULL, __VA_ARGS__)
+#else
+# define __VERBOSE__(lvl,...)      verbose(lvl, __FILE__, __LINE__, __func__, __VA_ARGS__)
+#endif
+
+# define _VERBOSE_(vlvl,llvl,...)  do{ if (verbosity >= vlvl) __VERBOSE__(llvl, __VA_ARGS__); } while(0)
+
 # define ERROR(...)                _VERBOSE_(Verbosity_Level_Error, Log_Level_Error, __VA_ARGS__)
 # define WARNING(...)              _VERBOSE_(Verbosity_Level_Warning, Log_Level_Warning, __VA_ARGS__)
 # define NOTICE(...)               _VERBOSE_(Verbosity_Level_Notice, Log_Level_Notice, __VA_ARGS__)
 # define INFO(...)                 _VERBOSE_(Verbosity_Level_Info, Log_Level_Info, __VA_ARGS__)
 # define DEBUG(...)                _VERBOSE_(Verbosity_Level_Debug, Log_Level_Debug, __VA_ARGS__)
+
 # define LOGUSER(app)              verbose_set_name(app,0)
 # define LOGAUTH(app)              verbose_set_name(app,1)