CMS MessageLogger: Controlling LogDebug Behavior

CMS MessageLogger Service
Controlling LogDebug Behavior

Code in user modules can be instrumented with LogDebug messages, intended for use when abnormal circumstances require the output of detailed information. In order that this instrumentation can be left in place without impacting performance under normal circmstances, it is important that LogDebug messages, by default, cost as little as possible in runtime overhead. That includes:

Since LogDebug messages are (by default) rapidly discarded, the user can explicitly enable LogDebug messages issued by some or all modules. This is done without needing to re-compile code, via parameters in the .cfg file.

For time-critical running, there is also a way to elminate the effect of LogDebug messages at compile-time. When this approach is used, the LogDebug calls will be optimized down to be truly zero-cost. The trade-off is that for code compiled with this switch set, the LogDebug messages cannot be explicitly enabled via parameters in the .cfg file.


Enabling LogDebug Messages

Code can be freely sprinkled with LogDebug messages, without fear of undue performance overhead: By default, each call to LogDebug("category") will consult a boolean variable to check whether debug messages are enabled for the current module. Unless debug messages have explicitly been enabled, LogDebug() will do no other work, and each operator<< to the LogDebug will merely check that same boolean and do no work either.

In order to "turn on" responses to LogDebug, the user does two things in the .cfg file, as illustrated by this example:

process TEST = {
  service = MessageLogger {
    vstring destinations = {   "detailedInfo.txt"
                             , "critical.txt"
                           }
    PSet detailedInfo.txt = { string threshold = "DEBUG"    } 
    vstring debugModules = {   "myAnalysisModule" 
                             , "myOtherModule   
			   }
  }
  untracked PSet maxEvents = {untracked int32 input = 5}
  path p = { myAnalysisModule, myOtherModule, aThirdModule }
  module myAnalysisModule = ModuleThatIssuesDebugMessages { }
  module myOtherModule    = ModuleThatIssuesDebugMessages { }
  module aThirdModule     = ModuleThatIssuesDebugMessages { }
  source = EmptySource { }
}
The string threshold = "DEBUG" parameter in the Pset for detailedInfo.txt specifies that the destination writing to that file should respond to all messages of severity DEBUG or higher -- that is, to all messages. By default the threshold is INFO, so in the above example, the destination writing to critical.txt would not report the LogDebug messages.

The vstring debugModules = {...} list specifies all the modules for which LogDebug should be enabled. As illustrated, these modules are specified by their module labels. In this example, LogDebug messages issued while in myAnalysisModule or myOtherModule would be enabled, while those issued while in aThirdModule would be rapidly discarded.

Enabling all LogDebug Messages

One further syntax is provided, for the convenience of users wishing to enable all LogDebug messages:
process TEST = {
  service = MessageLogger {
    vstring destinations = {   "detailedInfo.txt"
                             , "critical.txt"
                           }
    PSet detailedInfo.txt = { string threshold = "DEBUG"    } 
    vstring debugModules = {  "*"  } 
  }
  untracked PSet maxEvents = {untracked int32 input = 5}
  path p = { myAnalysisModule, myOtherModule, aThirdModule }
  module myAnalysisModule = ModuleThatIssuesDebugMessages { }
  module myOtherModule    = ModuleThatIssuesDebugMessages { }
  module aThirdModule     = ModuleThatIssuesDebugMessages { }
  source = EmptySource { }
}
(Remember that you still have to set one or more thresholds to DEBUG. Unless some destination(s) have their thresholds set at DEBUG, the LogDebug messages will be composed but no destination will report them.)

Compile-time Elimination of LogDebug Messages

If NDEBUG is defined (this is the same NDEBUG that would turn assert into nothingness), then the LogDebug macro will be transformed into a form that is easily optimized down to zero run-time cost.

If the code was compiled with NDEBUG defined, LogDebug messages will be completely suppressed (even if the .cfg file directs that they be enabled), since the code for testing whether such messages are enabled will not be present.

While the default behavior, as described above, is tied to the same NDEBUG that applies to assert macros, two additional symbols are provided to allow the user to over-ride that behavior.

Why are my LogDebug Messages Not Being Reported?

By design, the MessageLogger avoids (by default) reporting LogDebug messages, and discards such messages as rapidly as possible unless they are enabled. In addition, destinations' thresholds are set above that of DEBUG severity by default; again, users must specifically indicate that they want a destination to respond to LogDebug messages. This design choice was made so that users can instrument their code with (normally inactive) LogDebug diagnostics, and leave these in for future use without impacting performance when the information is not needed.

A consequence of this policy is that there are several points at which LogDebug message responses can be disabled, and the user requiring such output needs to enable both the issuing and the reporting of the messages.

If you are trying to get your LogDebug messages to be reported and they are not being shown, here is a checklist of reasons why LogDebug messages would not be reported by a destination:

  1. If the code is compiled with the NDEBUG symbol defined (for example, certain production compilations would do this to turn off assert checking), then the LogDebug macro is turned to a no-op.

    You can define the symbol ML_DEBUG to override this.

  2. If the .cfg file does not explicitly enable LogDebug messages for a given module, such messages issued by that module will be discarded. Make sure the parameter vstring debugModules = { "myModuleLabel" } is present in the MessageLogger parameter set. Check the spelling of debugModules and check that the module label suppied is the correct label. This label will appear outside the MessageLogger parameter set, on the left side of a module myModuleLabel = parameter and in the path = { ..., myModuleLabel, ...} parameter.

    vstring debugModules = { "*" } enables LogDebug messages from all modules.

  3. The threshold for every destination is, by default, set above the level that would permit LogDebug messaes to be reported. In the parameter set for the desired reporting destination, there must appear string threshold = "DEBUG"

USCMS Software and Computing Home Page - CMS MessageLogger Service Page


Mark Fischler
Last modified: December 1, 2005