- Attention
- In respect to the C++ Version of ALox, this manual is outdated. C++ Users, please visit ALib C++ Library.
The deep-link (we hope this still works, otherwise please quickly find it yourself from the above library link above) should be this.
1. Introduction
With the term "external configuration", we are addressing any type of configuration data that an application might have access to. The most common types of such configuration data are:
- Command line parameters
- Environment variables and
- Configuration files, e.g. "INI files"
For reading such configuration data, ALox relies on the facilities provided by underlying utility library ALib. Configuration mechanics of ALib are gathered in namespace [com::|cs::]aworx::lib::config. It is advisable to read the reference documentation (C++, C#, Java) of that namespace and its few classes.
In short, the features of the ALib configuration system are:
- A public static singleton of class Configuration (C++, C#, Java) is found in field ALIB.Config (C++, C#, Java).
- Class Configuration supports 'plug-ins' that read configuration data from different sources.
- Default plug-ins are those for reading command-line parameters and environment variables. In addition, a class to read (and write) INI files is provided and an instance of that class can easily be created and attached.
- Note
- But instead, ALib proposes to attach custom configuration file processing - use your own standard! What is need to be done is to write a small plug-in that translates requests to read (and if possible, also write) variables into your custom configuration system.
- The different plug-ins are asked for configuration data in a sequence defined by their priority. For example, command-line parameters have a higher priority than variables defined in an INI file. This way, command-line parameters 'overwrite' INI file entries.
- Variables can contain references to other variables. This concept named variable substitution, allows even more flexible configuration possibilities .
2. Relationship of ALox, Applications and Configuration Data
It may be very obvious to the reader, but lets spend a minute and think about the relationship of ALox and applications using it.
- ALox is embedded as a library in applications, they live in one process.
- ALox longs to read external configuration data
- The application itself probably does this as well and probably disposes of a system to maintain and read such data already
- ALox may want to write default values into the configuration (if a variable was not found)
In most use cases, the goal now is to enable ALox to access (read and write) the configuration that is already in place with the application. The huge benefit of this approach is, that no second configuration file or database is needed. And this is exactly what ALib - and therewith ALox - allows to achieve.
Then, other use cases and variants are:
- Having separated configuration systems for the application and ALox. For documentation on how to do this, see method ALox::Init (C#, Java).) respectively class lang::Camp (C++)
- Have no configuration system for ALox: The most obvious reason why this might be wanted is that a developer of an ALox enabled software might not want to allow the end user to reconfigure ALox (i.e. switching a Logger off that collects telemetric data).
- A mixed approach: Some ALox features should be configurable (from either configuration system) while other features should not be configurable from outside.
- Similar to this, some default values (that ALox creates on the fly) should automatically appear and be saved in the configuration. The benefit of this is that the user gets a fully filled configuration with maybe automatically commented entries that hints him/her to what is adjustable - all without reading manuals. Other of such ALox options probably should not automatically be saved. If not saved, these are regenerated as default values on the next run and again not be saved. A simple reason to disallow saving default values might be to avoid that the external configuration is being 'bloated' with ALox options that the user of an application is not interested in.
Finally, as ALox is a library, there might be more than one ALox enabled software running on the same system. Now, for configuration sources like INI files and command line parameters, this is not problematic. In the case of environment variables, it might become a problem: A variable setting here could influence more than one application if variables are not renamed on a per application basis.
3. How ALox Uses the ALib Configuration System
Well, as ALib and ALox are developed by the same team, of-course ALox uses the configuration system of ALib exactly as the ALib developers expect their users to do!
- Note
- For details consult the reference documentation (C++, C#, Java) provided with ALib.
In the JAVA and C# Version, ALox leaves field ALIB::ConfigCategory (C#, Java) untouched (it remains default "ALIB") while exposing an own, similar field ALox::ConfigCategory (C#, Java) defaulting to "ALOX". This allows a user of the library to change the category names
All configuration variables are declared in one place. (In Java and C# versions with static initializations of object of type class (struct) VariableDecl (C#, Java, in C++ with enumeration Variables (C++).)
When using interface method Configuration::Store (C++, C#, Java) to write configuration data, new variables are exclusively created within a plug-in set up at or below priority PrioDefaultValues (C++, C#, Java). By default, this is of type InMemoryPlugin (C++,C#, Java).
Finally, ALox leverages the flexibility that the priorities of the ALib configuration system brings by exposing parameter priority in methods Lox.SetVerbosity (C++, C#, Java) and Lox.SetSourcePathTrimRule (C++, C#). On the one hand, these methods are fully aligned with the configuration system, as parameter priority defaults to PrioDefaultValues (C++, C#, Java).
This way, what is set 'in code' is (by default) overruled by any type of external configuration. On the other hand, a programmer may specify a different priority and this way either allow only certain, higher prioritized external sources to overwrite, or just disallow it.
- Note
- Of-course, by just writing the corresponding values into the plug-in found with priority PrioProtectedValues (C++, C#, Java) such protection could be reached as well, but by exposing the parameter with the methods, an alternative, maybe more natural and less error prone way of implementing such protection is offered.
For the user of ALox, the benefits of the approach ALox takes are:
- ALox does not impose new requirements to the ALib configuration system. In respect to the plug-ins installed, everything remains untouched
- ALib allows to have its external variables modified in the following respect
- Variable names can be changed
- Category can be changed: either for a subset of the variables or for all. Even different category names can be chosen
- Default values of ALox variables can be changed
- Variable comments can be changed. Especially, those may come from a pool of externalized strings.
- Single ALox variables (or all) can be excluded from the possibility to be modified from outside.
- ALox will not bloat an applications' external configuration system with own variables, unless explicitly demanded:
- An application may also choose to expose only selected variables to the outside.
- An application may store ALib and ALox configuration data in a separated configuration file. (See ALox::Init (C++), C#, Java).)
- A custom configuration plug-in will not only work in respect to prioritizing values of external variables, but also in respect to consistency with ALox verbosity settings.
4. Concrete Steps on Integrating ALox Configuration in your Software
After the discussion of the previous sections it should be quite straightforward to understand how ALox is to be integrated to your software in respect to external configuration data. Here are some hints:
- Create a custom plug-in (using your custom config system) and attach it to singleton ALox.Config (C++, C#, Java).
- Create a class that has access to your config system
- implement the interface ConfigurationPlugin within this class
- Plug it in
Alternatively: create an instance of IniFile (C++, C#, Java) and attach this instead.
The following code samples this in C#:
static void Main( string[] args )
{
config.SetCommandLineArgs( args );
ALIB.Config.RemovePlugin( iniFile );
ALIB.Config.FetchFromDefault( iniFile );
iniFile.WriteFile();
ALIB.TerminationCleanUp();
}
- Set ALib::ConfigCategory and ALox::ConfigCategory to preferred values, e.g. your own application name (to avoid clashing of environment variables when two ALib enabled applications exist.
- If wanted, change the definitions of the various configuration variables, like:
- Set values that result from own application logic. A simple sample is command line parameter --verbose which might lead to 'programatically' changes in the domains' verbosities.
- Protect values that must not be changed from outside by storing a fixed value with priority PrioProtectedValues (C++, C#, Java)
Apply the previous two steps to one variable to redefine configuration behavior. Let's stick to the sample of having the --verbose switch. Imagine this option should get three possible values: 'silent', 'normal' and 'verbose'. The approach to take is the following:
- Programmatically add three new custom variables stored as protected values. Their names might be
MYAPP_VERBOSITY_1[2|3]
. These custom variables contain the verbosity settings for all Log Domains for each of the three switchable verbosities
- Depending on the command line switch, set the value of variable ALox.VERBOSITY (C++, C#, Java) to
"$MYAPP_VERBOSITY_1[2|3]"
, also in protected mode. The '$'
sign here substitutes the variables' value with the contents of named variable.
What is achieved here, is that there are custom 'presets' defined for the verbosities and those are all that the end-user can set!
Furthermore, if the substitution would be set to "$MYAPP_UNDOCUMENTED_SWITCH ; $MYAPP_VERBOSITY_1[2|3]"
then, in addition, a hidden new configuration variable is exposed. This might be used in "the field" when something goes wrong with a deployed application and more logging is wanted, because with this new undocumented variable each Log Domain is switchable again.
- Finally, before the termination of a process, copy those auto-generated ALox variables that you are interested in to your write-enabled configuration plug-in. This way, the user sees variables with comments and learns how to leverage those. The sample above uses method Configuration.FetchFromDefault (C++, C#, Java) to do so. This method copies all values not found in the given plug-in from the default values plug-in. Instead of using this simple method, a selective approach can be taken to copy exactly the values wanted.
5. C++ Language Version Specifics
What was said above is generally true for the C++ version of ALib/ALox. However, there are some differences:
- The library initialization process is a little more complex. It is done in different phases. To add a user-defined configuration plug-in, a first phase of initialization has to be performed. The details are documented with class lang::Camp (C++).
- Variable names, their defaults and help texts may be changed using external resources. For changing the resources, the library initialization has to be invoked in different phases. Details are documented with lang::resources (C++).
Next chapter: 13 - External Verbosity Configuration Back to index