ALox  V. 2402 R. 0
Home ALox for C++ ALox for C# ALox for Java Download
13 - External Verbosity Configuration

1. Introduction

This Chapter brings us back to talking about Log Domains and their attribute Verbosity which are associated with pairs of a Log Domains and a Logger.

Note
Please make sure that you have read and understood 04 - Log Domains before continue reading.

Setting such Verbosity by invoking Lox.SetVerbosity (C++, C#, Java) is easy and straightforward. However, when working in a team, different team members, working on different parts of a software, naturally are interested in different information. Now, when the Verbosity is defined in the source (preferably the bootstrap section of a software), then these would be randomly changed when checking source files in and out of a source control system. Therefore, ALox supports to read Verbosity settings from the command line, from environment variables, from an INI file or from any other custom data source. This way, all personal changes are outside the code - good for your team spirit!

But before we can explain how this is done, we first have to talk about priorities of Verbosity settings. This is an important prerequisite to understanding how external configuration works in ALox.

2. Priorities of Verbosity Settings

In the Tutorials (C++, C#, Java), in chapter 04 - Log Domains and elsewhere in the ALox documentation, so far, we have just ignored an optional parameter of overlaoded methods: Lox.SetVerbosity (C++, C#, Java). The parameter is named priority. We did so, because this parameter, while extending the flexibility of ALox, brings a new new level of complexity to the table. The good news is that (as explained in II - ALox Auto-Configuration and Orthogonality) when the parameter is omitted, ALox behaves as if this feature was not existing.

The parameter is of int type and defaults to constant PrioDefaultValues (C++, C#, Java). The value of the constant is 100, but for now, this is not of further interest. When passing a higher value here, subsequent invocations for the Log Domain in question (or for one of its parent domains!) which use the standard value, will be ignored. See the following sample:

Log.SetVerbosity( "DEBUG_LOGGER", Verbosity.Info, "/MYDOM", Configuration.PrioDefaultValues + 1 );
Log.Info( "MYDOM", "This line will be logged" );
Log.SetVerbosity( "DEBUG_LOGGER", Verbosity.Off, "/MYDOM" );
Log.Info( "MYDOM", "This line will still be logged" );

And its output:

UT_dox_manual.cs(564):Man_ExtVerbosityConfig()     [/MYDOM]: This line will be logged
UT_dox_manual.cs(567):Man_ExtVerbosityConfig()     [/MYDOM]: This line will still be logged

As you see, the second invocation of Lox.SetVerbosity is ignored, because the first had a higher priority.
With ALox internal logging (see 11 - Internal Logging) activated, ALox nicely reports what is going on. We add line:

Log.SetVerbosity( "DEBUG_LOGGER", Verbosity.Verbose, ALox.InternalDomains );

to the top of the sample. Now the output is:

UT_dox_manual.cs(580):Man_ExtVerbosityConfig()     [$/LGR ]: Logger "DEBUG_LOGGER": '$/'     = Verbosity.Verbose (Default).
UT_dox_manual.cs(582):Man_ExtVerbosityConfig()     [$/LGR ]: Logger "MEMORY" added.
UT_dox_manual.cs(582):Man_ExtVerbosityConfig()     [$/LGR ]: Logger "DEBUG_LOGGER": '/'      = Verbosity.Off     (Default).
UT_dox_manual.cs(582):Man_ExtVerbosityConfig()     [$/LGR ]: Logger "DEBUG_LOGGER": '/MYDOM' = Verbosity.Info    (Default).
UT_dox_manual.cs(582):Man_ExtVerbosityConfig()     [$/LGR ]: Logger "DEBUG_LOGGER": '/MYDOM' = Verbosity.Info    (10001).
UT_dox_manual.cs(583):Man_ExtVerbosityConfig()     [/MYDOM]: This line will be logged
UT_dox_manual.cs(585):Man_ExtVerbosityConfig()     [$/LGR ]: Logger "DEBUG_LOGGER": '/MYDOM' = Verbosity.Off     (Default). Lower priority (10000 < 10001). Remains Info.
UT_dox_manual.cs(586):Man_ExtVerbosityConfig()     [/MYDOM]: This line will still be logged

ALox in its internal log messages tells us that the second request was ignored.

Why is that useful? Well, honestly it really becomes useful only in consideration of external configuration data, described later in this chapter. However, when you think about it, one field of application is in respect to sub-domain settings. Consider the following Log Domain tree:

    /UI
    /UI/MOUSE
    /UI/DIALOGS
    /UI/DIALOGS/MOUSE
    /UI/DIALOGS/KEYS

Imagine you are currently frequently switching the Verbosity of sub-domains of Log Domain '/UI' because you are currently working on the UI. Now you have a random problem with mouse event handling. As long as this problem occurs, Log Statements related to mouse event should stay Verbose. Therefore, you enable them 'permanently' by invoking

Log.SetVerbosity( "DEBUG_LOGGER", Verbosity.Verbose, "/UI/MOUSE" , Configuration.PrioDefaultValues + 1 );
Log.SetVerbosity( "DEBUG_LOGGER", Verbosity.Verbose, "/UI/DIALOGS/MOUSE", Configuration.PrioDefaultValues + 1 );

After that, any changes in parent domains, even for root-domain, will not disable Log Statements of mouse events any more. When the mouse event handling is fixed, these settings can be deleted again.

Note
Once a priority of a Verbosity setting was increased, for the rest of the life-cycle of a process, this priority can not be changed back to a lower one. ALox does not provide an interface for that. The reason is simply, that the designers of ALox do not see any need in it. Honestly, if it was not so helpful for external configuration, the priority-feature of Verbosity settings would not have been implemented with ALox.

3. Priorities of External Configuration

As you have learned from the previous chapter, 12 - External Configuration, the configuration system of ALib (the utility library that ALox builds upon) works with priorities the same as ALox Verbosity settings do. Now, you might guess what happens! ALox uses the same constants as the ALib configuration system does. The following table gives an overview of these constants:

Constant Value
PrioProtectedValues (C++, C#, Java) <max int>
PrioCLIParameters (C++, C#, Java) 40000
PrioEnvironment (C++, C#, Java) 30000
PrioStandard (C++, C#, Java) 20000
PrioDefaultValues (C++,C#, Java) 10000
PrioAutodetect (C++, C#, Java) 500

When a Verbosity setting is read by ALox from external configuration, the priority of the plug-in that provided the data is used as the priority of the setting, just as if this value was passed to method Lox.SetVerbosity (C++, C#, Java) using optional parameter priority.

As a programmer, you need nothing special to do. The same as ALox creates Log Domains on the fly as soon as you are using them, the same it reads configuration data for these Log Domains without having an explicit mandate for that. It just always does. If no configuration plug-ins are set, nothing is read, ALox will not complain. However, if it finds configuration data that influences the Verbosity setting of Log Domains you are using, then you will get noted by ALox as soon as you have activated Internal Logging.

Before it is explained how the format of configuration looks like, lets talk about two important topics in respect to the priority values given in the table above.

  1. PrioDefaultValues
    As we have learned, constant Configuration.PrioDefaultValues is the default value for optional parameter priority of method Lox.SetVerbosity. Having the lowest value of all constants, this shows that any external configuration by default overwrites what is defined as for the Verbosity "in the source code".
    When you consider what was said in the introduction section of this chapter, then this makes perfect sense: Once you have defined your Verbosities externally, you do not need to care if team members put their own preferred "temporary" Lox.SetVerbosity invocations into the source. Your setup is just not affected by this!
    Consider settings made in the source code as pure default values - at least as long as you do not explicitly provide a different priority when invokeing the method.
  2. Configuration.PrioProtectedValues
    We have not talked about this one, although there are situations when using this might become very important:
    Attention
    In some use cases, logging may become a critical key feature of an application. For example when collection metrics from the field with deployed applications. In this case, a programmer may want to disallow to disable such logging. This can be achieved using priority constant Configuration.PrioProtectedValues with method Lox.SetVerbosity (C++, C#, Java). A Log Domain can not be "deactivated" with command line parameters or environment variables, as soon as this priority value is used.

4. Variable LOXNAME_LOGGERNAME_VERBOSITY

This was a lot of theory, before we now finally come to to the definition of the configuration variable itself. When a Logger is registered with an instance of class Lox, ALox tries to read configuration variable ALOX_LOXNAME_LOGGERNAME_VERBOSITY. (This is done also whenever a new Log Domain is used and hence created on the fly.)

The portions 'LOXNAME' and 'LOGGERNAME' of the variable name have to be replaced by the names of the instances of Lox and Logger in question.

Its format is:

ALOX_<LOXNAME>_<LOGGERNAME>_VERBOSITY = [ writeback [ VAR_NAME ] ; ] [*]domainpath[*] = verbosity [ ; … ]

Let quickly forget about the optional argument 'writeback' (we come back to this in the necht section) and just concentrate on:

[*]domainpath[*] = verbosity

which can appear repeatedly separated by a semicolon ';'. The pairs of domainpath and verbosity have the following meaning:

  • domainpath denotes the path of the Log Domain whose Verbosity is to be set. Optionally the value may contain wildcard character '*' at the beginning or end of the string or at both places.
  • Parameter verbosity
    The verbosity value as listed in enum class Verbosity (C++, C#, Java). The names given here are treated case insensitive.

With having the ability to provide wildcards, the possibilities to define the Verbosity is a little different than when using method Lox.SetVerbosity (C++, C#, Java)! The differences are:

  • Using configuration variables it is possible to fetch Log Domains which are residing in different sub-domain trees. For example, setting 'ERRORS', affects any Log Domain with this substring in the path, like

      /ERRORS
      /UI/DIALOGS/ERRORS
      /COMM/ERRORS/SEVERE
    

    This is not possible with using method Lox.SetVerbosity which always modifies exactly one Log Domain and its sub-domains.

  • Using method Lox.SetVerbosity, it is possible to use "relative path addressing", which means, a Log Domain or sub-domain of the evaluated, currently applicable domain resulting from Scope Domains, set can be addressed. Although it is not often recommended to do so, sometimes this possibility might be very helpful. For example to do a quick, temporary setting or for settings that are made explicitly "programatically", meaning those who are depending on state conditions of a software)

In general, as already described, controlling the Verbosity using configuration variables is preferred over using method Lox.SetVerbosity. This is the reason why ALox does not provide an interface method to set "rules", similar to those coming from configuration variables from within the source code.

Note
If you really, urgently want to have the same flexibility of setting the Verbosity for patterns of Log Domain paths from within your code, then your way to go is to save a corresponding configuration variable into the in-memory configuration plug-in found with PrioDefaultValues (C++, C#, Java) of the public static singleton of class ALox found in field Configuration.Default (C++, C#, Java). Of-course,you do this instead of invoking Lox.SetVerbosity.
Source code samples of how this is concretely done in the programming language of your choice can be found in the unit tests of ALox.
Note
To address the internal domain tree (see 11 - Internal Logging), provide string "INTERNAL_DOMAINS" for parameter domainpath. This can also be used as a prefix e.g.
  INTERNAL_DOMAINS/REPORT = verbose ;
However, a Logger that is not configured to log on internal Log Domain, can not be enabled for doing so using this configuration variable. A Logger has to be 'added' to the internal Log Domain tree once by the software itself. This behavior is wanted and similiar to the fact that a Logger can not be added to a different Lox instance by just adding the verbosity setting variable on the command line!

5. Let ALox Write the Variable

We had so far ignored the portion [ writeback [ VAR_NAME ] ; ] of configuration variable

ALOX_<LOXNAME>_<LOGGERNAME>_VERBOSITY = [ writeback [ VAR_NAME ] ; ] [*]domainpath[*] = verbosity [ ; … ]

The 'writeback' option tells ALox to write all verbosities back to the configuration as soon as a Logger is removed from a Lox object.

Note
Of-course, a write-enabled configuration plug-in needs to be registered with PrioDefaultValues (C++, C#, Java). The simplest type is found with class IniFile (C++, C#, Java). See the ALox samples on how to create and attach an ALib INI file to your software on bootstrap with just two lines of code. The following snippet is taken from C#:
static void Main( string[] args )
{
// first attach INI file to config system...
IniFile iniFile= new IniFile();
config.SetCommandLineArgs( args );
config.InsertPlugin( iniFile, Configuration.PrioStandard );
// .. then initialize ALox Logging Library
ALox.Init( config );
//...
//...
ALIB.Config.RemovePlugin( iniFile );
ALIB.Config.FetchFromDefault( iniFile );
iniFile.WriteFile();
ALIB.TerminationCleanUp();
}

Having ALox writing back the verbosities to your configuration is quite useful, for example, if you have an empty INI file and you want to start configuring ALox using this. Instead of manually building the variable, all you need to do is adding section and variable:

    [ALOX]
    LOG_DEBUG_LOGGER_VERBOSITY = writeback

The variable name addresses the default debug Logger which is called DEBUG_LOGGER and the default debug Lox which is called LOG.

Now after your next run of your application, ALox will have written back the current configuration and your INI might look like this:

    [ALOX]
    LOG_DEBUG_LOGGER_VERBOSITY = writeback;         \
                                 /                   =Info;        \
                                 /ACTION             =Info;        \
                                 /AWAX               =Info;        \
                                 /CMDLINE            =Info;        \
                                 /TILE               =Info;        \
                                 /WMI                =Info;        \
                                 /WMI/XLIB           =Info;        \
                                 /WMI/XLIB/RANDR     =Info;        \
                                 /WMI/XLIB/X11       =Info;        \

This of-course saves you some work. But there are more benefits. As you see, ALox preserves the attribute writeback in the variable. And you should keep this in. This way, on the next run of your software, the list might get extended by Log Domains that had not been registered on the previous runs. The reason is that ALox recognizes only those domains that are actually used (independend from their Verbosity setting). Subsequent runs may have different execution paths and this way might "touch" other Log Domains.

As ALox reads the variable during the runs, any change you make in the INI-file is well kept.

Note
When manually changing Verbosities it is OK to just use one character for the setting. E.g. change an "Info" to "w". Next time you run the application, ALox will write "Warning" and format the string accurately.

Let's imagine the developer of the application sampled above has some problems with interfacing the XWindow library. Hence, he or she would focus on the relevant domains and change the Verbosities to this:

    [ALOX]
    LOG_DEBUG_LOGGER_VERBOSITY = writeback;         \
                                 /                   =Warning;     \
                                 /ACTION             =Warning;     \
                                 /AWAX               =Info;        \
                                 /CMDLINE            =Off;         \
                                 /TILE               =Off;         \
                                 /WMI                =Info;        \
                                 /WMI/XLIB           =Verbose;     \
                                 /WMI/XLIB/RANDR     =Warning;     \
                                 /WMI/XLIB/X11       =Verbose;     \

Now, the X11 problems were fixed. However, the developer likes the detailing of the settings and aims to preserve them for the future. All he/she needs to do, is to add optional parameter VAR_NAME of the write back argument [ writeback [ VAR_NAME ] ; ] . The arbitrary variable name MYSTUFF_X11_DEBUG_VERB is added as shown here:

    [ALOX]
    LOG_DEBUG_LOGGER_VERBOSITY = writeback MYSTUFF_X11_DEBUG_VERB; \
                                 /                   =Warning;     \
                                 /ACTION             =Warning;     \
                                 /AWAX               =Info;        \
                                 /CMDLINE            =Off;         \
                                 /TILE               =Off;         \
                                 /WMI                =Info;        \
                                 /WMI/XLIB           =Verbose;     \
                                 /WMI/XLIB/RANDR     =Warning;     \
                                 /WMI/XLIB/X11       =Verbose;     \

After the next run, the INI file will contain:

    [ALOX]
    LOG_DEBUG_LOGGER_VERBOSITY = writeback MYSTUFF_X11_DEBUG_VERB; \
                                 /                   =Warning;     \
                                 /ACTION             =Warning;     \
                                 /AWAX               =Info;        \
                                 /CMDLINE            =Off;         \
                                 /TILE               =Off;         \
                                 /WMI                =Info;        \
                                 /WMI/XLIB           =Verbose;     \
                                 /WMI/XLIB/RANDR     =Warning;     \
                                 /WMI/XLIB/X11       =Verbose;     \


    [MYSTUFF]

    # Created at runtime through config option 'writeback' in variable "ALOX_LOG_DEBUG_LOGGER_VERBOSITY".
    X11_DEBUG_VERB=              /                   =Warning;     \
                                 /                   =Warning;     \
                                 /ACTION             =Warning;     \
                                 /AWAX               =Info;        \
                                 /CMDLINE            =Off;         \
                                 /TILE               =Off;         \
                                 /WMI                =Info;        \
                                 /WMI/XLIB           =Verbose;     \
                                 /WMI/XLIB/RANDR     =Warning;     \
                                 /WMI/XLIB/X11       =Verbose;     \

As you see, ALox created INI file section MYSTUFF and added the variable we specified. You can still fine-tune the verbosity setting in LOG_DEBUG_LOGGER_VERBOSITY or chose different execution paths of your software. On each run, ALox will save what is found in variable ALOX_LOG_DEBUG_LOGGER_VERBOSITY to variable MYSTUFF_X11_DEBUG_VERB! Once you think that the setting is OK, you can stop the writeback feature by changing the Loggers Verbosity setting in the INI file to:

    [ALOX]
    LOG_DEBUG_LOGGER_VERBOSITY = $MYSTUFF_X11_DEBUG_VERB

    [MYSTUFF]
    ...
    ...

Now we are using a feature of the ALib configuration system called Variable Substitution (C++, C#, Java): With the preceding '$' symbol (this is the default and can be changed), class Configuration substitutes what is "$MYSTUFF_X11_DEBUG_VERB" with the corresponding variable.

To conclude, lets take some further notes on what was said above:

  • What was done above, of-course might be repeated and different sets of Verbosities might be saved in different custom variables. Once this is done, switching the verbosities between different "debug use-cases", is a matter of changing the substitution variable in variable LOXNAME_LOGGERNAME_VERBOSITY.
  • Of-course, the configuration sets stored can be shortened easily to contain only non-redundant information. ALox, when writing the variable, includes all sub-domains in the list of settings, even those that have the same Verbosity as their parent domain. This is intentionally done to support the user and decrease typing.

    Once a setting is fixed, all redundant lines can be deleted easily - but again this is not necessary even, it might just increase readability and shorten the configuration file.

  • When execution paths are changing between different runs, ALox will remove Verbosity information provided, if a Log Domain was not used. The advantage of this is, that when Log Domains are renamed in the source code, no "garbage" remains in the config file - at least for freshly written variables. If you want to compare an 'old' variable with what the difference would be using the newest version of your software, variable ALOX_LOG_DEBUG_LOGGER_VERBOSITY can be set as follows:

      [ALOX]
      LOG_DEBUG_LOGGER_VERBOSITY = writeback MY_NEW_VAR ; $MY_OLD_VAR
    

    After running the software MY_NEW_VAR will not contain Log Domains that are not existing any more (or have not been touched by the execution path!) but will contain new domains (or those that previously had not been touched by the execution path).

  • For the variable name optionally provided with argument writeback, if in anonymous category, the same rules on using the underscore character '_' apply as it is described in Variable Substitution (C++, C#, Java).
  • With more complex use cases, there are even new options: For example, when having different configuration files like system-wide and user specific files, with a deployed application, substituted variables might reside "fixed" in the system-wide configuration, while each user locally can address these variables and use them. Or, a command line parameter could use a variable substitution with the substitute residing in a configuration file.
  • The whole concept can also be used 'in code'. As a sample think of a command line application that provides different "own verbosities" with a command line parameter like --verbosity <val>. Now, the software could write a variable of e.g. ALOX_REL_CONSOLE_VERBOSITY (a release logger responsible for the software's standard output) with either PrioDefaultValues (C++, C#, Java) or PrioProtectedValues (C++, C#, Java) (use the latter to disallow the user to hack in). The value of the variable set 'in code' would either contain substituted system-wide external variables, or hard-coded strings (again, depending on the necessary protection level of the software).

6. Wrap-up

As a summary, these are the takeaways of this chapter:

  • ALox has an optional priority with method Lox.SetVerbosity which is fully orthogonal in its use. This means, when omitted ALox works as if this feature was not existing.
  • The priority of Verbosity settings taken by itself is not a fundamental game changer in respect to the flexibility and overall value of ALox. Nevertheless in some situations, some tricky things might be performed. (OK, here is another sample: an external library periodically changes the Verbosity of certain Log Domains - which by design it should not do. As we do not have access to the source code of that library, using a higher priority for a setting from outside the library fixes this)
  • The recommended way to set Verbosities - especially when working in a team - is to use external configuration variables.
  • It is possible to overwrite different data sources, e.g. use an environment variable to overwrite what is given in an iniFile. Or to have two INI files, one local, user dependent and one general, public instance. The user-dependent INI file may modify (overwrite) settings of the general one.
  • In special situations it is recommended to protect certain Log Domains from being changed at runtime. This is done by explicitly providing PrioProtectedValues (C++, C#, Java) to method Lox.SetVerbosity. A similar issue is described for Domain Substitution here.
  • External setting of Verbosity has different (partly more, partly less) possibilities in comparison to "programatically" setting. A way to extend the programatically setting to work the same as external configuration, is by using an in-memory INI file.

Next chapter: 14 - Trimming Source File Paths and Clickable IDE Output
Back to index
ALox
lox::ALox ALox
Verbosity
Verbosity
Configuration
config::Configuration Configuration
Log
lox::Log Log
IniFile
config::IniFile IniFile