[Libreoffice] Assertions and Logging

Norbert Thiebaud nthiebaud at gmail.com
Mon Nov 21 21:35:15 PST 2011


On Fri, Nov 18, 2011 at 8:25 AM, Stephan Bergmann <sbergman at redhat.com> wrote:
>>
>>    Second, at runtime the environment variable SAL_LOG further limits
>> which
>>    macro calls actually generate log output.  The environment varialbe
>> SAL_LOG
>>    must either be unset or must match the regular expression

The run tine flexibility is a great feature, but the proposed
implementation is scary perf-wise

you don't want to re-parse the log-config at every log message.

You need to parse it once and for all... and not use string but enum
to identify the module/category you want to trace.

as a one-time steup cost you parse you env variable and initialize a
static array, which for each module/category contain the max
acceptable level of log
(0 = no log, 1=error, 2=warn, 3=info (4=debug?)

the test of log-ability should  be a simple if( array[module] >=
level) and the macro writtin so that the no-trace path is as cheap as
possible.

To illustrate (this is for pure C where each 'module' actually have a
init_module function to dynamically register themselves to the tracing
system... that may not work nicely in c++ (ironically), but the
general gist is the same:

(excerpt)

header:

#define _msgs_out(rc) { msgs_trace_intern("%s <-- 0x%x", __func__, rc);};
#define _msgs_cond(lvl) if((lvl <= MSGS_BUILD_TRACE_LEVEL) && (lvl <=
MSGS_CONTEXT->level))

#define msgs_major     _msgs_cond(LVL_MAJOR)     msgs_trace_intern
#define msgs_normal    _msgs_cond(LVL_NORMAL)    msgs_trace_intern
#define msgs_minor     _msgs_cond(LVL_MINOR)     msgs_trace_intern
#define msgs_detail    _msgs_cond(LVL_DETAIL)    msgs_trace_intern
#define msgs_verbose   _msgs_cond(LVL_VERBOSE)   msgs_trace_intern
#define msgs_debug     _msgs_cond(LVL_DEBUG)     msgs_trace_intern
#define msgs_logorrhea _msgs_cond(LVL_LOGORRHEA) msgs_trace_intern
#define msgs_uncond    msgs_trace_intern


static inline void msgs_trace_intern(const char format[], ...)
{
va_list list;

    va_start(list, format);
    msgs_do_trace(MSGS_CONTEXT, format, list);
    va_end(list);
}

here MSGS_CONTEXT could be &g_aModules_Context[module_id] , modifying
the api above, adding a module_id parm (in my case the module_id is
implicit based on the location of the trace)

Note: the lvl <= MSGS_BUILD_TRACE_LEVEL in _msgs_cond means that the
whole things is optimized out at compile if the test is false (both
part of the test are actually build time constant. the second part f
the test means thta the test cost just a couple of integer compare to
fail.

Note that I have an intermediary static inlinee msgs_trace_intern due
to the fact that I use a static variable MSGS_CONTEXT, static to each
'module'... in you case you do not need that, if you do a full
centralized pre-registration.

Note that you can use:

log(writer,....)

 and in the define of the log macro use module ## _LOG_ID to refer to
the enum value, and #module to have a pretty sting to print, so that
your log still show a human readable module name

for example, I use something like :

/* We need two macro here, to have a proper expansion of the 'module'
parameter */
#define CORE_DECLARE_MODULE(module) CORE_DECLARE_MODULE2(module)

#define CORE_DECLARE_MODULE2(module) \
static struct msgs_module_context g_context = { module ##  _MODULE_ID
, -1, 0, 0, NULL,  #module}

to define my module_level context

Norbert


More information about the LibreOffice mailing list