Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component balm_metrics
[Package balm]

Provide a suite of operations for recording metric values. More...

Namespaces

namespace  balm

Detailed Description

Outline
Purpose:
Provide a suite of operations for recording metric values.
Classes:
See also:
Component balm_collector, Component balm_integercollector, Component balm_defaultmetricsmanager
Description:
This component provides a suite of macros to simplify the process of collecting metrics. A metric records the number of times an event occurs, as well as an associated measurement value. A metric maintains a count of event occurrences and the aggregated minimum, maximum, and total of the measured metric-event values. Note that this component does not define what constitutes an event nor what the associated value represents.
Alternative Systems for Telemetry:
Bloomberg software may alternatively use the GUTS telemetry API, which is integrated into Bloomberg infrastructure.
Thread Safety:
All the macros defined in this component are thread-safe, meaning that they can be safely invoked simultaneously from multiple threads. It is not safe, however, to invoke any of the macros defined in this component while the default metrics manager is being either created or destroyed.
Macro Summary:
This section provides a brief description of the macros defined in this component. In most cases, category and metric names supplied as macro arguments are required to be runtime constants, meaning that their values must be constant for the lifetime of the process. More complete documentation is provided in the Macro Reference section.
   BALM_METRICS_IF_CATEGORY_ENABLED(CATEGORY)
       This macro behaves like an 'if' clause, executing the subsequent
       (compound) statement if the specified 'CATEGORY' is enabled.

   BALM_METRICS_UPDATE(CATEGORY, METRIC1, VALUE1)
   BALM_METRICS_UPDATE2(CATEGORY, METRIC1, VALUE1, METRIC2, VALUE2)
   BALM_METRICS_UPDATE3(CATEGORY, METRIC1, VALUE1, ..., METRIC3, VALUE3)
   BALM_METRICS_UPDATE4(CATEGORY, METRIC1, VALUE1, ..., METRIC4, VALUE4)
   BALM_METRICS_UPDATE5(CATEGORY, METRIC1, VALUE1, ..., METRIC5, VALUE5)
   BALM_METRICS_UPDATE6(CATEGORY, METRIC1, VALUE1, ..., METRIC6, VALUE6)
   BALM_METRICS_INT_UPDATE(CATEGORY, METRIC1, VALUE1)
   BALM_METRICS_INT_UPDATE2(CATEGORY, METRIC1, VALUE1, METRIC2, VALUE2)
   BALM_METRICS_INT_UPDATE3(CATEGORY, METRIC1, VALUE1, ..., METRIC3, VALUE3)
   BALM_METRICS_INT_UPDATE4(CATEGORY, METRIC1, VALUE1, ..., METRIC4, VALUE4)
   BALM_METRICS_INT_UPDATE5(CATEGORY, METRIC1, VALUE1, ..., METRIC5, VALUE5)
   BALM_METRICS_INT_UPDATE6(CATEGORY, METRIC1, VALUE1, ..., METRIC6, VALUE6)
       Update each of up to 6 metrics by the corresponding values.
       The supplied category and metric names must be *runtime* *constants*.

   BALM_METRICS_TYPED_UPDATE(CATEGORY, METRIC, VALUE, PREFERRED_TYPE)
   BALM_METRICS_TYPED_INT_UPDATE(CATEGORY, METRIC, VALUE, PREFERRED_TYPE)
       Update the identified metric by 'VALUE' and set its preferred
       publication type.  'CATEGORY' and 'METRIC' must be *runtime*
       *constants*.

   BALM_METRICS_INCREMENT(CATEGORY, METRIC)
       Increment (by 1) the identified metric.  'CATEGORY' and 'METRIC' must
       be *runtime* *constants*.

   BALM_METRICS_TYPED_INCREMENT(CATEGORY, METRIC, PREFERRED_TYPE)
       Increment (by 1) the identified metric and set the metric's preferred
       publication type.  'CATEGORY' and 'METRIC' must be *runtime*
       *constants*.

   BALM_METRICS_DYNAMIC_UPDATE(CATEGORY, METRIC, VALUE)
   BALM_METRICS_DYNAMIC_INT_UPDATE(CATEGORY, METRIC, VALUE)
       Update the identified metric by 'VALUE'.  This operation performs a
       lookup on 'CATEGORY' and 'METRIC' on each invocation, so those values
       need *not* be runtime constants.

   BALM_METRICS_DYNAMIC_INCREMENT(CATEGORY, METRIC)
       Increment (by 1) the identified metric.  This operation performs a
       lookup on 'CATEGORY' and 'METRIC' on each invocation, so those values
       need *not* be runtime constants.

   BALM_METRICS_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS)
   BALM_METRICS_TIME_BLOCK_SECONDS(CATEGORY, METRIC)
   BALM_METRICS_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC)
   BALM_METRICS_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC)
   BALM_METRICS_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC)
       Update the identified metric by the elapsed (wall) time, in the
       indicated units, from the instantiation point of the macro to the end
       of the enclosing lexical scope.  'CATEGORY' and 'METRIC' must
       be *runtime* *constants*.

   BALM_METRICS_DYNAMIC_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS)
   BALM_METRICS_DYNAMIC_TIME_BLOCK_SECONDS(CATEGORY, METRIC)
   BALM_METRICS_DYNAMIC_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC)
   BALM_METRICS_DYNAMIC_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC)
   BALM_METRICS_DYNAMIC_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC)
       Update the identified metric by the elapsed (wall) time, in the
       indicated units, from the instantiation point of the macro to the end
       of the enclosing lexical scope.  This operation performs a lookup on
       'CATEGORY' and 'METRIC' on each invocation, so those values need *not*
       be runtime constants.
Macro Reference:
The macros defined in this component make use of the default instance of balm::MetricsManager. The macros have no effect unless the metrics manager default instance has been initialized via a call to balm::DefaultMetricsManager::create.
The macros defined below provide two basic operations identified by their suffixes: update (*_UPDATE) and increment (*_INCREMENT). The update operation increments (by 1) the identified metric's count of events, increases the metric's total by the supplied value, if the supplied value is less than the metric's current minimum value then the minimum value is set to the supplied value, and if the supplied value is greater than the metric's current maximum value then the maximum value is set to the supplied value. The increment operation is logically equivalent to an update of 1.
The update, increment, and timing operations come in two variations: standard, and dynamic (DYNAMIC). The standard variation maintains a (function-scope static) cache containing the identity of the metric being collected. This cache is initialized the first time the flow of control passes through the instantiated macro, which in practice means that the identifiers for the metric(s) passed as parameters to that macro must be runtime constants. The dynamic variant looks up the supplied category and metric(s) on each invocation of the macro, resulting in additional runtime overhead compared to the standard variant.
The following are the standard (non-dynamic) macros provided by this component for updating a metric's value:
   BALM_METRICS_UPDATE(CATEGORY, METRIC, VALUE)
       Update the indicated metric, identified by the specified 'CATEGORY'
       and 'METRIC' names, with the specified 'VALUE'.  'CATEGORY' and
       'METRIC' must be null-terminated strings of a type convertible to
       'const char *', and 'VALUE' is assumed to be of a type convertible to
       'double'.  This macro maintains a (function-scope static) cache
       containing the identity of the metric being updated.  This cache is
       initialized using the 'CATEGORY' and 'METRIC' specified on the *first*
       application of this macro at a particular instantiation point;
       subsequent applications use that cached information, which in
       practice means that 'CATEGORY' and 'METRIC' must be *runtime*
       *constants*.  If the default metrics manager has not been
       initialized, or if the indicated 'CATEGORY' is currently disabled,
       this macro has no effect.

   BALM_METRICS_INT_UPDATE(CATEGORY, METRIC, VALUE)
       Update the indicated metric, identified by the specified 'CATEGORY'
       and 'METRIC' names, with the specified *integer* 'VALUE'.  'CATEGORY'
       and 'METRIC' must be null-terminated strings of a type convertible to
       'const char *', and 'VALUE' is assumed to be of a type convertible to
       'int'.  This macro maintains a (function-scope static) cache
       containing the identity of the metric being updated.  This cache is
       initialized using the 'CATEGORY' and 'METRIC' specified on the *first*
       application of this macro at a particular instantiation point;
       subsequent applications use that cached information, which in
       practice, means that 'CATEGORY' and 'METRIC' must be *runtime*
       *constants*.  If the default metrics manager has not been initialized,
       or if the indicated 'CATEGORY' is currently disabled, this macro has
       no effect.

   BALM_METRICS_UPDATE2(CATEGORY, METRIC1, VALUE1, METRIC2, VALUE2)
   BALM_METRICS_UPDATEn(CATEGORY, METRIC1, VALUE1, ..., METRICn, VALUEn)
                                                            Where 2 <= n <= 6
       Update each of the indicated metrics, identified by the specified
       'CATEGORY' name and the respective metric names 'METRIC1', 'METRIC2',
       ..., 'METRICn' (2 <= n <= 6), with the corresponding specified
       'VALUE1', 'VALUE2', ..., 'VALUEn'.  'CATEGORY' and 'METRIC1',
       'METRIC2', ..., 'METRICn', must be null-terminated strings of a type
       convertible to 'const char *', and 'VALUE1', 'VALUE2', ..., 'VALUEn'
       are assumed to be of a type convertible to 'double'.  These macros
       maintain a (function-scope static) cache containing the identity of
       the metrics being updated.  This cache is initialized using the
       'CATEGORY' and metric identifiers specified on the *first*
       application of these macros at a particular instantiation point;
       subsequent applications use that cached information, which in
       practice means that the 'CATEGORY' and metric identifiers must be
       *runtime* *constants*.  If the default metrics manager has not been
       initialized, or if the indicated 'CATEGORY' is currently disabled,
       these macros have no effect.

   BALM_METRICS_INT_UPDATE2(CATEGORY, METRIC1, VALUE1, METRIC2, VALUE2)
   BALM_METRICS_INT_UPDATEn(CATEGORY, METRIC1, VALUE1, ..., METRICn, VALUEn)
                                                            Where 2 <= n <= 6
       Update each of the indicated metrics, identified by the specified
       'CATEGORY' name and the respective metric names 'METRIC1', 'METRIC2',
       ..., 'METRICn' (2 <= n <= 6), with the corresponding specified
       *integer* 'VALUE1', 'VALUE2', ..., 'VALUEn'.  'CATEGORY' and
       'METRIC1', 'METRIC2', ..., 'METRICn', must be null-terminated strings
       of a type convertible to 'const char *', and 'VALUE1', 'VALUE2', ...,
       'VALUEn' are assumed to be of a type convertible to 'int'.  These
       macros maintain a (function-scope static) cache containing the
       identity of the metrics being updated.  This cache is initialized
       using the 'CATEGORY' and metric identifiers specified on the *first*
       application of these macros at a particular instantiation point;
       subsequent applications use that cached information, which in
       practice means that the 'CATEGORY' and metric identifiers must be
       *runtime* *constants*.  If the default metrics manager has not been
       initialized, or if the indicated 'CATEGORY' is currently disabled,
       these macros have no effect.

   BALM_METRICS_TYPED_UPDATE(CATEGORY,
                             METRIC,
                             VALUE,
                             PREFERRED_PUBLICATION_TYPE)
   BALM_METRICS_TYPED_INT_UPDATE(CATEGORY,
                                 METRIC,
                                 VALUE,
                                 PREFERRED_PUBLICATION_TYPE)
       The behavior of these macros is logically equivalent to
       'BALM_METRICS_UPDATE(CATEGORY, METRIC, VALUE)' and
       'BALM_METRICS_INT_UPDATE(CATEGORY, METRIC, VALUE)', respectively,
       except that, on the first invocation, these macros also set the
       indicated metric's 'PREFERRED_PUBLICATION_TYPE'.  The preferred
       publication type of a metric indicates the preferred aggregate to
       publish for that metric (e.g., 'COUNT', 'TOTAL', 'MIN', 'MAX', or
       'RATE').  The behavior is undefined unless
       'PREFERRED_PUBLICATION_TYPE' is convertible to
       'balm::PublicationType::Value'.  Note that there is no uniform
       definition for how publishers will interpret this value; an
       'UNSPECIFIED' value, however, generally indicates that all of the
       collected aggregates (total, count, minimum, and maximum value)
       should be published.

   BALM_METRICS_INCREMENT(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to:
       'BALM_METRICS_INT_UPDATE(CATEGORY, METRIC, 1)'.

   BALM_METRICS_TYPED_INCREMENT(CATEGORY, METRIC, PREFERRED_TYPE)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_TYPED_UPDATE(CATEGORY, METRIC, 1, PREFERRED_TYPE)'.
The following are the dynamic macros provided by this component for updating a metric's value; these macros do not statically cache the identity of the metric and look up the supplied CATEGORY and METRIC on each invocation:
   BALM_METRICS_DYNAMIC_UPDATE(CATEGORY, METRIC, VALUE)
       Update the indicated metric, identified by the specified 'CATEGORY'
       and 'METRIC' names, by the specified 'VALUE'.  'CATEGORY' and
       'METRIC' must be null-terminated strings of a type convertible to
       'const char *', and 'VALUE' is assumed to be of a type convertible to
       'double'.  If the default metrics manager has not been initialized,
       or if the indicated 'CATEGORY' is currently disabled, this macro has
       no effect.  Note that this operation looks up the 'CATEGORY'
       and 'METRIC' on *each* application, resulting in (unnecessary)
       additional runtime overhead (if the 'CATEGORY' and 'METRIC' values are
       always the same for a particular point of call).

   BALM_METRICS_DYNAMIC_INT_UPDATE(CATEGORY, METRIC, VALUE)
       Update the indicated metric, identified by the specified 'CATEGORY'
       and 'METRIC' names, by the specified *integer* 'VALUE'.  'CATEGORY'
       and 'METRIC' must be null-terminated strings of a type convertible to
       'const char *', and 'VALUE' is assumed to be of a type convertible
       to 'int'.  If the default metrics manager has not been initialized,
       or if the indicated 'CATEGORY' is currently disabled, this macro has
       no effect.  Note that this operation looks up the 'CATEGORY'
       and 'METRIC' on *each* application, resulting in (unnecessary)
       additional runtime overhead (if the 'CATEGORY' and 'METRIC' values
       are always the same for a particular point of call).

   BALM_METRICS_DYNAMIC_INCREMENT(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_DYNAMIC_INT_UPDATE(CATEGORY, METRIC, 1)'.
The following macro, BALM_METRICS_IF_CATEGORY_ENABLED, allows clients to (efficiently) determine if a (runtime constant) category is enabled:
   BALM_METRICS_IF_CATEGORY_ENABLED(CATEGORY)
       This macro behaves like an 'if' clause, executing the subsequent
       (compound) statement if the specified 'CATEGORY' is enabled.
       'CATEGORY' must be a null-terminated string of a type convertible to
       'const char *'.  If the default metrics manager has not been
       initialized, or if the indicated 'CATEGORY' is currently disabled,
       the following statement is not executed (i.e., the 'if'-condition
       is 'false').  This macro maintains a (function-scope static) cache
       containing the identity of the category.  This cache is initialized
       using the 'CATEGORY' specified on the *first* application of this
       macro at a particular instantiation point; subsequent applications
       use that cached information, which in practice means that
       'CATEGORY' must be a *runtime* *constant*.  *WARNING*: although the
       'BALM_METRICS_IF_CATEGORY_ENABLED' may look like a function call,
       it actually consists of a declaration and an 'if' statement, which
       means that the following is syntactically *incorrect*:
       'if (BALM_METRICS_IF_CATEGORY_ENABLED("myCategory")) { stuff() }'.
       That should instead be written as:
       'BALM_METRICS_IF_CATEGORY_ENABLED("myCategory") { stuff(); }'.
Finally, this component provides a set of macros to record the elapsed wall time of a block of code:
   BALM_METRICS_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS)
       Update the indicated metric, identified by the specified 'CATEGORY'
       and 'METRIC' names, by the elapsed (wall) time, in the specified
       'TIME_UNITS', from the point of instantiation of the macro to the end
       of the enclosing lexical scope.  'CATEGORY' and 'METRIC'  must be
       null-terminated strings of a type convertible to 'const char *',
       while 'TIME_UNITS' is assumed to be of a type convertible to the
       enumerated type 'balm::StopwatchScopedGuard::Units'.  This macro
       maintains a (function-scope static) cache containing the identity of
       the metric being updated.  This cache is initialized using the
       'CATEGORY' and 'METRIC' specified on the *first* application of this
       macro at a particular instantiation point; subsequent applications
       use that cached information, which in practice means that
       'CATEGORY' and 'METRIC' must be *runtime* *constants*.  If the
       default metrics manager has not been initialized, or the identified
       'CATEGORY' is disabled, this macro has no effect.  Note that
       'TIME_UNITS' indicates the scale of value to report, but does *not*
       affect the precision of the elapsed time measurement.

   BALM_METRICS_TIME_BLOCK_SECONDS(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_TIME_BLOCK' called with
       'balm::StopwatchScopedGuard::k_SECONDS'.

   BALM_METRICS_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_TIME_BLOCK' called with
       'balm::StopwatchScopedGuard::k_MILLISECONDS'.

   BALM_METRICS_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_TIME_BLOCK' called with
       'balm::StopwatchScopedGuard::k_MICROSECONDS'.

   BALM_METRICS_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_TIME_BLOCK' called with
       'balm::StopwatchScopedGuard::k_NANOSECONDS'.

   BALM_METRICS_DYNAMIC_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS)
       Update the indicated metric, identified by the specified 'CATEGORY'
       and 'METRIC' names, by the elapsed (wall) time, in the specified
       'TIME_UNITS', from the instantiation of the macro to the end of the
       enclosing lexical scope.  'CATEGORY' and 'METRIC'  must be
       null-terminated strings of a type convertible to 'const char *',
       while 'TIME_UNITS' is assumed to be of a type convertible to the
       enumerated type 'balm::StopwatchScopedGuard::Units'.  If the default
       metrics manager has not been initialized, or the identified
       'CATEGORY' is disabled, this macro has no effect.  Note that
       this operation looks up the 'CATEGORY' and 'METRIC' on *each*
       application, resulting in (unnecessary) additional runtime overhead
       (if the 'CATEGORY' and 'METRIC' values are always the same for a
       particular point of call).  Also note that 'TIME_UNITS' indicates the
       scale of value to report, but does *not* affect the precision of the
       elapsed time measurement.

   BALM_METRICS_DYNAMIC_TIME_BLOCK_SECONDS(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_DYNAMIC_TIME_BLOCK' called with
       'balm::StopwatchScopedGuard::k_SECONDS'.

   BALM_METRICS_DYNAMIC_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_DYNAMIC_TIME_BLOCK' called with
       'balm::StopwatchScopedGuard::k_MILLISECONDS'.

   BALM_METRICS_DYNAMIC_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_DYNAMIC_TIME_BLOCK' called with
       'balm::StopwatchScopedGuard::k_MICROSECONDS'.

   BALM_METRICS_DYNAMIC_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC)
       The behavior of this macro is logically equivalent to
       'BALM_METRICS_DYNAMIC_TIME_BLOCK' called with
       'balm::StopwatchScopedGuard::k_NANOSECONDS'.
Usage:
The following examples demonstrate how to configure, collect, and publish metrics.
Example 1: Create and Configure the Default balm::MetricsManager Instance:
This example demonstrates how to create the default balm::MetricsManager instance and perform a trivial configuration.
First we create a balm::DefaultMetricsManagerScopedGuard, which manages the lifetime of the default metrics manager instance. At construction, we provide this guard with an output stream (stdout) to which the default metrics manager will publish metrics. Note that the default metrics manager is intended to be created and destroyed by the owner of main: An instance of the manager should be created during the initialization of an application (while the task has a single thread) and destroyed just prior to termination (when there is similarly a single thread).
  int main(int argc, char *argv[])
  {
      // ...

      balm::DefaultMetricsManagerScopedGuard managerGuard(bsl::cout);
Once the default manager object has been created, it can be accessed using the instance operation.
      balm::MetricsManager *manager =
                                     balm::DefaultMetricsManager::instance();
      assert(0 != manager);
Note that the default metrics manager will be released when the managerGuard exits this scoped and is destroyed. Clients that choose to explicitly call balm::DefaultMetricsManager::create() must also explicitly call balm::DefaultMetricsManager::release().
Example 2: Updating a Metric:
Once a metrics manager is initialized, we can use the various macros to record metric values. In this second example, we collect metrics from a hypothetical event-processing function. We use BALM_METRICS_UPDATE to record the size of the data being processed to a metric named "msgSize", and the elapsed time (in milliseconds) to process the event to a metric named "elapsedTime". Finally, we use BALM_METRICS_INCREMENT to record a count of failures to a metric named "failureCount". Note that we do not use the *_DYNAMIC_* variants of the BALM_METRICS_UPDATE or BALM_METRICS_INCREMENT macros because the category and metric names are constant across all applications of the macro at a particular instantiation point (the DYNAMIC variants look up the category and metric name on each application, which would incur unnecessary runtime overhead).
  int processEvent(int eventId, const bsl::string& eventMessage)
      // Process the event described by the specified 'eventId' and
      // 'eventMessage'.  Return 0 on success, and a non-zero
      // value otherwise.
  {
      (void)eventId;

      int returnCode = 0;

      BALM_METRICS_UPDATE("processEvent",
                          "msgSize",
                          static_cast<double>(eventMessage.size()));
      BALM_METRICS_TIME_BLOCK_MILLISECONDS("processingEvent", "elapsedTime");

      // Process 'data'.

      if (0 != returnCode) {
          BALM_METRICS_INCREMENT("processEvent", "failureCount");
      }

      return returnCode;
  }
Example 3: Using BALM_METRICS_IF_CATEGORY_ENABLED:
In this next example, we use BALM_METRICS_IF_CATEGORY_ENABLED to conditionally disable a (relatively) expensive operation involved in computing a metric value. The processEvent2 function, defined below, uses a bsls::Stopwatch to record the elapsed system, user, and wall times, associated with processing the event. The system calls used (via bsls::Stopwatch) to record the elapsed time may be relatively expensive, so we use BALM_METRICS_IF_CATEGORY_ENABLED to ensure we perform those operations only if metrics collection is enabled. Finally, we use BALM_METRICS_UPDATE3 to update the three metrics, which is (slightly) more efficient than updating each metric individually using BALM_METRIC_UPDATE.
  int processEvent2(int eventId, const bsl::string& eventMessage)
      // Process the event described by the specified 'eventId' and
      // 'eventMessage'.  Return 0 on success, and a non-zero
      // value otherwise.
  {
      (void)eventId;
      (void)eventMessage;

      int returnCode = 0;

      bsls::Stopwatch stopwatch;
      BALM_METRICS_IF_CATEGORY_ENABLED("processEvent2") {
         stopwatch.start(true);
      }

      // Process 'data'.

      BALM_METRICS_IF_CATEGORY_ENABLED("processEvent2") {
         double systemTime, userTime, wallTime;
         stopwatch.accumulatedTimes(&systemTime, &userTime, &wallTime);
         BALM_METRICS_UPDATE3("processEvent2",
                              "systemTime", systemTime,
                              "userTime",   userTime,
                              "wallTime",   wallTime);
      }

      return returnCode;
  }