Search code examples
design-patternslanguage-agnostic

Logging and Configuration Systems: Circular Dependency


Assume a typical scenario where the initial settings of an application are loaded at startup from a configuration file. The application also has a logger. The parameters of the logger (e.g. verbosity level, log file path, etc.) are ideally also stored in the configuration file. However, it is also desirable that the configuration loader log information about parameter loading, for example

Attempting to load parameter LogVerbosity. Parameter is absent. Using the default value: 4.

Thus, we see a circular dependency between the two components. The configuration loader needs a ready-to-use logger, and a logger needs configuration parameters to initialize itself. This seems to me to be a problem typical enough to have canonical solutions to it, but I was unable to find anything.

Of course, one can roll some ad-hoc solutions but I'm interested in the best industry practices.

Hope the question makes sense.


Solution

  • I would say that the canonical solution is: don't mix logging and configuration!

    Imagine that there is a bug triggered by the configuration file parsing (but you don't know that yet!). You change the configuration file to enable logging. Now the parsing doesn't trigger the bug, and everything looks right, until you disable logging again...

    So: more generically, and by principle, one wants to minimize the disruption that the debugging infrastructure (including logging) introduces to a program; in the ideal case, debugging functionality would be orthogonal to anything that the application does, to avoid causing heisenbugs. Mixing normal configuration with logging configuration is already against this principle.

    But also empirically, you can see how the well-known logging libraries work: they all have their own configuration files, independent of any configuration going on in the application, so you can change the logging behaviour without ever messing with the application itself. So you can repeat a problematic run of an application, only changing its logging behaviour and hopefully nothing else. That's how Log4j and its family of ports, or the already mentioned nlog, work.