Page MenuHomePhabricator

Eina Log module
Updated 1,921 Days AgoPublic

Users

For users, this will help you to figure out source of problems. Developers may ask you the output and give you the exact command line to run, but one example is:

EINA_LOG_LEVEL=4 expedite -e xlib

This will run expedite benchmark tool with all logging domains at level 4 (debug, the greater the number, the more verbose it will be). It should show lots of output lines like:

DBG:eina_module eina_amalgamation.c:8811 eina_module_list_load() array 0x65ca10, count 0

The line is easily grep-able, the first 3 letters are the log level name or number if it's less than zero or greater than 4. Then follows the domain name (eina_module in the example) followed by the source file (eina_amalgamation.c), line (8811), function name (eina_module_list_load) and then the message.

It should be colored as well, making it easier to spot different levels and domains.

To disable colors, use the environment variable EINA_LOG_COLOR_DISABLE=1

If one dislikes having both file/line and function (often they are redundant), then disable one of them with EINA_LOG_FILE_DISABLE=1 or EINA_LOG_FUNCTION_DISABLE=1. Do not use both, in that case just function will be disabled as file/line is more specific (and thus useful).

If program is multi-threaded and thread-safe logging is initialized (eina_log_threads_enable()), then logging from other threads (any other thread than the one that called eina_init()) you'll see another component: [T:XXXX] where XXXX is the thread number. This is to make sure the code is running in the proper place.

What is interesting about eina log is domain support. This enables us to see debug log for one module while seeing information for another and just warnings for the rest. Let's say we want to see debug for eina_module, info for eina_stringshare but just warning for everything else, we'd use the following command:

EINA_LOG_LEVEL=2 EINA_LOG_LEVELS=eina_module:4,eina_stringshare:3 expedite -e xlib

The first variable sets the generic log, as explained above. The new variable EINA_LOG_LEVELS specifies a comma separated list of domain:level. Domain names are specified in source code and is not dependent on file name, so developers should document available domains.

Extra User Features

Optimize out extra debugging

Often users want to squeeze the last bit of performance from their systems and logging may introduce minimal overhead. The great thing is that users of EINA_LOG_* macros can be optimized out by restricting the maximum log level at compile time, just configure with --with-internal-maximum-log-level=NUMBER, for example:

./configure --with-internal-maximum-log-level=2

will remove all info (3), debug (4) or greater levels. This avoid function calls and runtime checks.

Developers

For developers it's easy: either use the global domain EINA_LOG_DOMAIN_GLOBAL or register your own domain.

Using the global domain can be handy to quick debug, but it's not recommended for the long run. To use it, one can use pre-defined macros: EINA_LOG_CRIT(), EINA_LOG_ERR(), EINA_LOG_WARN(), EINA_LOG_INFO() and EINA_LOG_DBG(). These macros are like printf() and should be easy to convert an application using printf() or fprintf() to it.

To register your own domain it's as simple as calling the function eina_log_domain_register(), it returns the log domain identifier that should be used with macros like EINA_LOG(), EINA_LOG_DOM_CRIT(), EINA_LOG_DOM_ERR() and so on. To make life easier, it's advised that applications declare their own macros. Example:

Using in a single C file

#include <Eina.h>

static int _log_dom = -1;

#define ERR(...) EINA_LOG_DOM_ERR(_log_dom, __VA_ARGS__)
#define DBG(...) EINA_LOG_DOM_DBG(_log_dom, __VA_ARGS__)

Eina_Bool my_code_init(void) {
   if (!eina_init()) { /* you should init eina before registering log */
      return EINA_FALSE;
   }

   if (_log_dom < 0) {
      _log_dom = eina_log_domain_register("my_code", NULL);
      if (_log_dom < 0) {
         EINA_LOG_CRIT("could not register log domain 'my_code'");
         eina_shutdown();
         return EINA_FALSE;
      }
   }

   DBG("initialized!");
   return EINA_TRUE;
}

void my_code_shutdown(void) {
    if (_log_dom >= 0) {
       DBG("shutdown!");
       eina_log_domain_unregister(_log_dom);
       _log_dom = -1;
       eina_shutdown();
    }
}

void my_code_func(int val) {
    DBG("val=%d", val);
    if (val < 1) ERR("val less than 1, val=%d", val);
}

Using from multiple C files

Your private (my_code_private.h) header should contain:

#include <Eina.h>
extern int _my_code_log_dom = -1;

#define ERR(...) EINA_LOG_DOM_ERR(_my_code_log_dom, __VA_ARGS__)
#define DBG(...) EINA_LOG_DOM_DBG(_my_code_log_dom, __VA_ARGS__)

Your main source file:

#include "my_code_private.h"

Eina_Bool my_code_init(void) {
   if (!eina_init()) { /* you should init eina before registering log */
      return EINA_FALSE;
   }

   if (_log_dom < 0) {
      _my_code_log_dom = eina_log_domain_register("my_code", NULL);
      if (_my_code_log_dom < 0) {
         EINA_LOG_CRIT("could not register log domain 'my_code'");
         eina_shutdown();
         return EINA_FALSE;
      }
   }

   DBG("initialized!");
   return EINA_TRUE;
}

void my_code_shutdown(void) {
    if (_my_code_log_dom >= 0) {
       DBG("shutdown!");
       eina_log_domain_unregister(_log_dom);
       _my_code_log_dom = -1;
       eina_shutdown();
    }
}

Your secondary files:

#include "my_code_private.h"

void my_code_func(int val) {
    DBG("val=%d", val);
    if (val < 1) ERR("val less than 1, val=%d", val);
}

Extra developer features

Abort on Critical

One can define EINA_LOG_ABORT=1 to make eina abort on levels less or equal to critical. This level is used by safety checks and other paths and can make debug easier, just run it from inside gdb and it will stop on failure.

Logging from threads

If you need to log from threads, call eina_log_threads_enable() before doing so. After that function, any log from threads other than the main (thread where the first eina_init() was called) will be reported with the thread id.

Imported from https://trac.enlightenment.org/e/wiki/EinaLog
History:
1 barbieri 2009-09-16 21:03:38
2 barbieri 2009-09-16 21:09:56
3 barbieri 2009-09-16 21:18:57
4 Thanatermesis 2009-10-08 08:09:24
5 T_UNIX 2009-10-29 02:52:49 added a missing ';'
6 dieb 2009-12-15 16:31:40

Last Author
beber
Last Edited
Sep 5 2013, 2:35 PM
Projects
None
Subscribers
None