diff --git a/include/maestro/env.h b/include/maestro/env.h index edd9c60f2547d91c2aaaf5ab6813a1cf34a77ee8..0d95b73a21a19b4fbae924559b4183bcd904d61d 100644 --- a/include/maestro/env.h +++ b/include/maestro/env.h @@ -63,6 +63,26 @@ */ #define MSTRO_ENV_LOG_LEVEL "MSTRO_LOG_LEVEL" +/**@brief Selection of modules that should log (Optional) + * + * Maestro log messages are annotated with a module name; by default + * all modules are permitted to log. This variable can be set to + * selectively disable or enable certain modules. + * + * The syntax is + * component1,component2,^component3,... + * + * where 'component1' indicates that it should be included, and + * '^component3' indicates that component3 should be excluded. + * + * The pseudo-component 'all' may be used to indicate all + * components. This can be used to set a 'background', and either + * selectively include or exclude components. + * + * If unset, the default is "all". + */ +#define MSTRO_ENV_LOG_MODULES "MSTRO_LOG_MODULES" + /**@brief Log color. (Optional) * * Maestro logging color (ANSI) can be changed at application startup by diff --git a/maestro/logging.c b/maestro/logging.c index 854046237a1596773987c27ad0dfe1ac270e1881..78c8e2158a898a45214378e4b4cec9e54cf62d1c 100644 --- a/maestro/logging.c +++ b/maestro/logging.c @@ -261,6 +261,77 @@ static _Atomic(bool) g_queried_env = false; static int g_log_dst = MSTRO_LOG_DST_STDERR; static char *g_env_debug_flag = NULL; +static uint64_t g_log_module_mask = MSTRO_LOG_MODULE_ALL; + +static const struct mstro_log_module_descriptor +g_module_descriptors[] = MSTRO_LOG_MODULES; + + +static inline +uint64_t mstro_log__parse_module_spec(char *module_spec) +{ + uint64_t result=0; + char *sep = ","; + char *word; + const size_t num_modules = (sizeof(g_module_descriptors)/ + sizeof(struct mstro_log_module_descriptor)); + + for (word = strtok(module_spec, sep); + word; + word = strtok(NULL, sep)) { + char *modulename = word; + bool flip = false; + if(word[0]=='^') { + flip=true; + modulename++; + } + uint64_t val=0; + if(strcasecmp("all",modulename)==0) { + val = MSTRO_LOG_MODULE_ALL; + } else { + for(size_t i=0; i<num_modules; i++) { + if(strcasecmp(g_module_descriptors[i].name, modulename)==0) { + val = g_module_descriptors[i].selector; + break; + } + } + } + if(val==0) { + LOG_ERR(MSTRO_LOG_MODULE_CORE, + "Invalid module specifier %s in module specification %s, skipping\n", + modulename, module_spec); + } else { + /* LOG_DEBUG(MSTRO_LOG_MODULE_CORE, */ + /* "Parsed |%s|, value %" PRIx64 ", complement? %d, result %" PRIx64" moves to %" PRIx64"\n", */ + /* word, val, flip, result, */ + /* flip? result & ~val : result |val); */ + + if(!flip) { + result |= val; + } else { + result &= ~val; + } + } + } + /* LOG_DEBUG(MSTRO_LOG_MODULE_CORE, "Parsed |%s| as %" PRIx64 "\n", */ + /* module_spec, result); */ + return result; +} + +static inline +const char *mstro_log_module_name(uint64_t module) +{ + /* FIXME: We could hash on the module */ + const size_t num_modules = (sizeof(g_module_descriptors)/ + sizeof(struct mstro_log_module_descriptor)); + for(size_t i=0; i<num_modules; i++) { + if((module & g_module_descriptors[i].selector)!=0) { + return g_module_descriptors[i].name; + } + } + return "???"; +} + /* one-time init function for log infrastructure */ static inline void @@ -270,6 +341,8 @@ mstro_log__init() atomic_exchange(&g_queried_env, true); if(!already_initialized) { + g_pid=getpid(); + const char *env_log_dst = getenv(MSTRO_ENV_LOG_DST); if(env_log_dst!=NULL) { LOG_NOISE(MSTRO_LOG_MODULE_CORE, @@ -327,29 +400,21 @@ mstro_log__init() if(env_color_errors!=NULL) { g_color_errors = true; } + + char *env_module_val = getenv(MSTRO_ENV_LOG_MODULES); + if(env_module_val==NULL) { + env_module_val="all"; + } + g_log_module_mask = mstro_log__parse_module_spec(env_module_val); + LOG_DEBUG(MSTRO_LOG_MODULE_CORE, + "Environment variable %s select log modules %" PRIx64 "\n", + MSTRO_ENV_LOG_MODULES, g_log_module_mask); - g_pid=getpid(); /* thread ID can't be set here, every thread sets it at first call */ } } -static const struct mstro_log_module_descriptor -g_module_descriptors[] = MSTRO_LOG_MODULES; - -static inline -const char *mstro_log_module_name(uint64_t module) -{ - /* FIXME: We could hash on the module */ - const size_t num_modules = (sizeof(g_module_descriptors)/ - sizeof(struct mstro_log_module_descriptor)); - for(size_t i=0; i<num_modules; i++) { - if((module & g_module_descriptors[i].selector)!=0) { - return g_module_descriptors[i].name; - } - } - return "???"; -} void mstro_vlocation_aware_log(int level, @@ -362,7 +427,10 @@ mstro_vlocation_aware_log(int level, assert(level>=0); assert(level<MSTRO_log__MAX); - if(level <= g_debug_level) { + if(level <= g_debug_level + && (module & g_log_module_mask)) { + /* fprintf(stderr,"module %" PRIx64 ", mask %" PRIx64 "\n", */ + /* module, g_log_module_mask); */ const char *thread_desc = mstro__ensure_threadid(); if(g_instance_identifier==NULL) {