BDE 4.14.0 Production release
Loading...
Searching...
No Matches
balm_metrics.h
Go to the documentation of this file.
1/// @file balm_metrics.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balm_metrics.h -*-C++-*-
8#ifndef INCLUDED_BALM_METRICS
9#define INCLUDED_BALM_METRICS
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balm_metrics balm_metrics
15/// @brief Provide a suite of operations for recording metric values.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balm
19/// @{
20/// @addtogroup balm_metrics
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balm_metrics-purpose"> Purpose</a>
25/// * <a href="#balm_metrics-classes"> Classes </a>
26/// * <a href="#balm_metrics-description"> Description </a>
27/// * <a href="#balm_metrics-alternative-systems-for-telemetry"> Alternative Systems for Telemetry </a>
28/// * <a href="#balm_metrics-thread-safety"> Thread Safety </a>
29/// * <a href="#balm_metrics-macro-summary"> Macro Summary </a>
30/// * <a href="#balm_metrics-macro-reference"> Macro Reference </a>
31/// * <a href="#balm_metrics-usage"> Usage </a>
32/// * <a href="#balm_metrics-example-1-create-and-configure-the-default-balm-metricsmanager-instance"> Example 1: Create and Configure the Default balm::MetricsManager Instance </a>
33/// * <a href="#balm_metrics-example-2-updating-a-metric"> Example 2: Updating a Metric </a>
34/// * <a href="#balm_metrics-example-3-using-balm_metrics_if_category_enabled"> Example 3: Using BALM_METRICS_IF_CATEGORY_ENABLED </a>
35///
36/// # Purpose {#balm_metrics-purpose}
37/// Provide a suite of operations for recording metric values.
38///
39/// # Classes {#balm_metrics-classes}
40///
41///
42/// @see balm_collector, balm_integercollector, balm_defaultmetricsmanager
43///
44/// # Description {#balm_metrics-description}
45/// This component provides a suite of macros to simplify the
46/// process of collecting metrics. A metric records the number of times an
47/// event occurs, as well as an associated measurement value. A metric
48/// maintains a count of event occurrences and the aggregated minimum, maximum,
49/// and total of the measured metric-event values. Note that this component
50/// does *not* define what constitutes an event nor what the associated value
51/// represents.
52///
53/// ## Alternative Systems for Telemetry {#balm_metrics-alternative-systems-for-telemetry}
54///
55///
56/// Bloomberg software may alternatively use the GUTS telemetry API, which is
57/// integrated into Bloomberg infrastructure.
58///
59/// ## Thread Safety {#balm_metrics-thread-safety}
60///
61///
62/// All the macros defined in this component are *thread-safe*, meaning that
63/// they can be safely invoked simultaneously from multiple threads. It is
64/// *not* safe, however, to invoke any of the macros defined in this component
65/// while the default metrics manager is being either created or destroyed.
66///
67/// ## Macro Summary {#balm_metrics-macro-summary}
68///
69///
70/// This section provides a brief description of the macros defined in this
71/// component. In most cases, category and metric names supplied as macro
72/// arguments are required to be *runtime* *constants*, meaning that their
73/// values must be constant for the lifetime of the process. More complete
74/// documentation is provided in the `Macro Reference` section.
75/// @code
76/// BALM_METRICS_IF_CATEGORY_ENABLED(CATEGORY)
77/// This macro behaves like an 'if' clause, executing the subsequent
78/// (compound) statement if the specified 'CATEGORY' is enabled.
79///
80/// BALM_METRICS_UPDATE(CATEGORY, METRIC1, VALUE1)
81/// BALM_METRICS_UPDATE2(CATEGORY, METRIC1, VALUE1, METRIC2, VALUE2)
82/// BALM_METRICS_UPDATE3(CATEGORY, METRIC1, VALUE1, ..., METRIC3, VALUE3)
83/// BALM_METRICS_UPDATE4(CATEGORY, METRIC1, VALUE1, ..., METRIC4, VALUE4)
84/// BALM_METRICS_UPDATE5(CATEGORY, METRIC1, VALUE1, ..., METRIC5, VALUE5)
85/// BALM_METRICS_UPDATE6(CATEGORY, METRIC1, VALUE1, ..., METRIC6, VALUE6)
86/// BALM_METRICS_INT_UPDATE(CATEGORY, METRIC1, VALUE1)
87/// BALM_METRICS_INT_UPDATE2(CATEGORY, METRIC1, VALUE1, METRIC2, VALUE2)
88/// BALM_METRICS_INT_UPDATE3(CATEGORY, METRIC1, VALUE1, ..., METRIC3, VALUE3)
89/// BALM_METRICS_INT_UPDATE4(CATEGORY, METRIC1, VALUE1, ..., METRIC4, VALUE4)
90/// BALM_METRICS_INT_UPDATE5(CATEGORY, METRIC1, VALUE1, ..., METRIC5, VALUE5)
91/// BALM_METRICS_INT_UPDATE6(CATEGORY, METRIC1, VALUE1, ..., METRIC6, VALUE6)
92/// Update each of up to 6 metrics by the corresponding values.
93/// The supplied category and metric names must be *runtime* *constants*.
94///
95/// BALM_METRICS_TYPED_UPDATE(CATEGORY, METRIC, VALUE, PREFERRED_TYPE)
96/// BALM_METRICS_TYPED_INT_UPDATE(CATEGORY, METRIC, VALUE, PREFERRED_TYPE)
97/// Update the identified metric by 'VALUE' and set its preferred
98/// publication type. 'CATEGORY' and 'METRIC' must be *runtime*
99/// *constants*.
100///
101/// BALM_METRICS_INCREMENT(CATEGORY, METRIC)
102/// Increment (by 1) the identified metric. 'CATEGORY' and 'METRIC' must
103/// be *runtime* *constants*.
104///
105/// BALM_METRICS_TYPED_INCREMENT(CATEGORY, METRIC, PREFERRED_TYPE)
106/// Increment (by 1) the identified metric and set the metric's preferred
107/// publication type. 'CATEGORY' and 'METRIC' must be *runtime*
108/// *constants*.
109///
110/// BALM_METRICS_DYNAMIC_UPDATE(CATEGORY, METRIC, VALUE)
111/// BALM_METRICS_DYNAMIC_INT_UPDATE(CATEGORY, METRIC, VALUE)
112/// Update the identified metric by 'VALUE'. This operation performs a
113/// lookup on 'CATEGORY' and 'METRIC' on each invocation, so those values
114/// need *not* be runtime constants.
115///
116/// BALM_METRICS_DYNAMIC_INCREMENT(CATEGORY, METRIC)
117/// Increment (by 1) the identified metric. This operation performs a
118/// lookup on 'CATEGORY' and 'METRIC' on each invocation, so those values
119/// need *not* be runtime constants.
120///
121/// BALM_METRICS_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS)
122/// BALM_METRICS_TIME_BLOCK_SECONDS(CATEGORY, METRIC)
123/// BALM_METRICS_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC)
124/// BALM_METRICS_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC)
125/// BALM_METRICS_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC)
126/// Update the identified metric by the elapsed (wall) time, in the
127/// indicated units, from the instantiation point of the macro to the end
128/// of the enclosing lexical scope. 'CATEGORY' and 'METRIC' must
129/// be *runtime* *constants*.
130///
131/// BALM_METRICS_DYNAMIC_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS)
132/// BALM_METRICS_DYNAMIC_TIME_BLOCK_SECONDS(CATEGORY, METRIC)
133/// BALM_METRICS_DYNAMIC_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC)
134/// BALM_METRICS_DYNAMIC_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC)
135/// BALM_METRICS_DYNAMIC_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC)
136/// Update the identified metric by the elapsed (wall) time, in the
137/// indicated units, from the instantiation point of the macro to the end
138/// of the enclosing lexical scope. This operation performs a lookup on
139/// 'CATEGORY' and 'METRIC' on each invocation, so those values need *not*
140/// be runtime constants.
141/// @endcode
142///
143/// ## Macro Reference {#balm_metrics-macro-reference}
144///
145///
146/// The macros defined in this component make use of the default instance of
147/// `balm::MetricsManager`. The macros have no effect unless the metrics
148/// manager default instance has been initialized via a call to
149/// `balm::DefaultMetricsManager::create`.
150///
151/// The macros defined below provide two basic operations identified by their
152/// suffixes: update (`*_UPDATE`) and increment (`*_INCREMENT`). The update
153/// operation increments (by 1) the identified metric's count of events,
154/// increases the metric's total by the supplied value, if the supplied value
155/// is less than the metric's current minimum value then the minimum value is
156/// set to the supplied value, and if the supplied value is greater than the
157/// metric's current maximum value then the maximum value is set to the supplied
158/// value. The increment operation is logically equivalent to an update of 1.
159///
160/// The update, increment, and timing operations come in two variations:
161/// standard, and dynamic (*<u>DYNAMIC</u>*). The standard variation maintains a
162/// (function-scope static) cache containing the identity of the metric being
163/// collected. This cache is initialized the *first* time the flow of control
164/// passes through the instantiated macro, which in practice means that the
165/// identifiers for the metric(s) passed as parameters to that macro must be
166/// *runtime* *constants*. The dynamic variant looks up the supplied category
167/// and metric(s) on each invocation of the macro, resulting in additional
168/// runtime overhead compared to the standard variant.
169///
170/// The following are the standard (non-dynamic) macros provided by this
171/// component for updating a metric's value:
172/// @code
173/// BALM_METRICS_UPDATE(CATEGORY, METRIC, VALUE)
174/// Update the indicated metric, identified by the specified 'CATEGORY'
175/// and 'METRIC' names, with the specified 'VALUE'. 'CATEGORY' and
176/// 'METRIC' must be null-terminated strings of a type convertible to
177/// 'const char *', and 'VALUE' is assumed to be of a type convertible to
178/// 'double'. This macro maintains a (function-scope static) cache
179/// containing the identity of the metric being updated. This cache is
180/// initialized using the 'CATEGORY' and 'METRIC' specified on the *first*
181/// application of this macro at a particular instantiation point;
182/// subsequent applications use that cached information, which in
183/// practice means that 'CATEGORY' and 'METRIC' must be *runtime*
184/// *constants*. If the default metrics manager has not been
185/// initialized, or if the indicated 'CATEGORY' is currently disabled,
186/// this macro has no effect.
187///
188/// BALM_METRICS_INT_UPDATE(CATEGORY, METRIC, VALUE)
189/// Update the indicated metric, identified by the specified 'CATEGORY'
190/// and 'METRIC' names, with the specified *integer* 'VALUE'. 'CATEGORY'
191/// and 'METRIC' must be null-terminated strings of a type convertible to
192/// 'const char *', and 'VALUE' is assumed to be of a type convertible to
193/// 'int'. This macro maintains a (function-scope static) cache
194/// containing the identity of the metric being updated. This cache is
195/// initialized using the 'CATEGORY' and 'METRIC' specified on the *first*
196/// application of this macro at a particular instantiation point;
197/// subsequent applications use that cached information, which in
198/// practice, means that 'CATEGORY' and 'METRIC' must be *runtime*
199/// *constants*. If the default metrics manager has not been initialized,
200/// or if the indicated 'CATEGORY' is currently disabled, this macro has
201/// no effect.
202///
203/// BALM_METRICS_UPDATE2(CATEGORY, METRIC1, VALUE1, METRIC2, VALUE2)
204/// BALM_METRICS_UPDATEn(CATEGORY, METRIC1, VALUE1, ..., METRICn, VALUEn)
205/// Where 2 <= n <= 6
206/// Update each of the indicated metrics, identified by the specified
207/// 'CATEGORY' name and the respective metric names 'METRIC1', 'METRIC2',
208/// ..., 'METRICn' (2 <= n <= 6), with the corresponding specified
209/// 'VALUE1', 'VALUE2', ..., 'VALUEn'. 'CATEGORY' and 'METRIC1',
210/// 'METRIC2', ..., 'METRICn', must be null-terminated strings of a type
211/// convertible to 'const char *', and 'VALUE1', 'VALUE2', ..., 'VALUEn'
212/// are assumed to be of a type convertible to 'double'. These macros
213/// maintain a (function-scope static) cache containing the identity of
214/// the metrics being updated. This cache is initialized using the
215/// 'CATEGORY' and metric identifiers specified on the *first*
216/// application of these macros at a particular instantiation point;
217/// subsequent applications use that cached information, which in
218/// practice means that the 'CATEGORY' and metric identifiers must be
219/// *runtime* *constants*. If the default metrics manager has not been
220/// initialized, or if the indicated 'CATEGORY' is currently disabled,
221/// these macros have no effect.
222///
223/// BALM_METRICS_INT_UPDATE2(CATEGORY, METRIC1, VALUE1, METRIC2, VALUE2)
224/// BALM_METRICS_INT_UPDATEn(CATEGORY, METRIC1, VALUE1, ..., METRICn, VALUEn)
225/// Where 2 <= n <= 6
226/// Update each of the indicated metrics, identified by the specified
227/// 'CATEGORY' name and the respective metric names 'METRIC1', 'METRIC2',
228/// ..., 'METRICn' (2 <= n <= 6), with the corresponding specified
229/// *integer* 'VALUE1', 'VALUE2', ..., 'VALUEn'. 'CATEGORY' and
230/// 'METRIC1', 'METRIC2', ..., 'METRICn', must be null-terminated strings
231/// of a type convertible to 'const char *', and 'VALUE1', 'VALUE2', ...,
232/// 'VALUEn' are assumed to be of a type convertible to 'int'. These
233/// macros maintain a (function-scope static) cache containing the
234/// identity of the metrics being updated. This cache is initialized
235/// using the 'CATEGORY' and metric identifiers specified on the *first*
236/// application of these macros at a particular instantiation point;
237/// subsequent applications use that cached information, which in
238/// practice means that the 'CATEGORY' and metric identifiers must be
239/// *runtime* *constants*. If the default metrics manager has not been
240/// initialized, or if the indicated 'CATEGORY' is currently disabled,
241/// these macros have no effect.
242///
243/// BALM_METRICS_TYPED_UPDATE(CATEGORY,
244/// METRIC,
245/// VALUE,
246/// PREFERRED_PUBLICATION_TYPE)
247/// BALM_METRICS_TYPED_INT_UPDATE(CATEGORY,
248/// METRIC,
249/// VALUE,
250/// PREFERRED_PUBLICATION_TYPE)
251/// The behavior of these macros is logically equivalent to
252/// 'BALM_METRICS_UPDATE(CATEGORY, METRIC, VALUE)' and
253/// 'BALM_METRICS_INT_UPDATE(CATEGORY, METRIC, VALUE)', respectively,
254/// except that, on the first invocation, these macros also set the
255/// indicated metric's 'PREFERRED_PUBLICATION_TYPE'. The preferred
256/// publication type of a metric indicates the preferred aggregate to
257/// publish for that metric (e.g., 'COUNT', 'TOTAL', 'MIN', 'MAX', or
258/// 'RATE'). The behavior is undefined unless
259/// 'PREFERRED_PUBLICATION_TYPE' is convertible to
260/// 'balm::PublicationType::Value'. Note that there is no uniform
261/// definition for how publishers will interpret this value; an
262/// 'UNSPECIFIED' value, however, generally indicates that all of the
263/// collected aggregates (total, count, minimum, and maximum value)
264/// should be published.
265///
266/// BALM_METRICS_INCREMENT(CATEGORY, METRIC)
267/// The behavior of this macro is logically equivalent to:
268/// 'BALM_METRICS_INT_UPDATE(CATEGORY, METRIC, 1)'.
269///
270/// BALM_METRICS_TYPED_INCREMENT(CATEGORY, METRIC, PREFERRED_TYPE)
271/// The behavior of this macro is logically equivalent to
272/// 'BALM_METRICS_TYPED_UPDATE(CATEGORY, METRIC, 1, PREFERRED_TYPE)'.
273/// @endcode
274/// The following are the dynamic macros provided by this component for
275/// updating a metric's value; these macros do not statically cache the
276/// identity of the metric and look up the supplied `CATEGORY` and `METRIC` on
277/// each invocation:
278/// @code
279/// BALM_METRICS_DYNAMIC_UPDATE(CATEGORY, METRIC, VALUE)
280/// Update the indicated metric, identified by the specified 'CATEGORY'
281/// and 'METRIC' names, by the specified 'VALUE'. 'CATEGORY' and
282/// 'METRIC' must be null-terminated strings of a type convertible to
283/// 'const char *', and 'VALUE' is assumed to be of a type convertible to
284/// 'double'. If the default metrics manager has not been initialized,
285/// or if the indicated 'CATEGORY' is currently disabled, this macro has
286/// no effect. Note that this operation looks up the 'CATEGORY'
287/// and 'METRIC' on *each* application, resulting in (unnecessary)
288/// additional runtime overhead (if the 'CATEGORY' and 'METRIC' values are
289/// always the same for a particular point of call).
290///
291/// BALM_METRICS_DYNAMIC_INT_UPDATE(CATEGORY, METRIC, VALUE)
292/// Update the indicated metric, identified by the specified 'CATEGORY'
293/// and 'METRIC' names, by the specified *integer* 'VALUE'. 'CATEGORY'
294/// and 'METRIC' must be null-terminated strings of a type convertible to
295/// 'const char *', and 'VALUE' is assumed to be of a type convertible
296/// to 'int'. If the default metrics manager has not been initialized,
297/// or if the indicated 'CATEGORY' is currently disabled, this macro has
298/// no effect. Note that this operation looks up the 'CATEGORY'
299/// and 'METRIC' on *each* application, resulting in (unnecessary)
300/// additional runtime overhead (if the 'CATEGORY' and 'METRIC' values
301/// are always the same for a particular point of call).
302///
303/// BALM_METRICS_DYNAMIC_INCREMENT(CATEGORY, METRIC)
304/// The behavior of this macro is logically equivalent to
305/// 'BALM_METRICS_DYNAMIC_INT_UPDATE(CATEGORY, METRIC, 1)'.
306/// @endcode
307/// The following macro, `BALM_METRICS_IF_CATEGORY_ENABLED`, allows clients to
308/// (efficiently) determine if a (*runtime* *constant*) category is enabled:
309/// @code
310/// BALM_METRICS_IF_CATEGORY_ENABLED(CATEGORY)
311/// This macro behaves like an 'if' clause, executing the subsequent
312/// (compound) statement if the specified 'CATEGORY' is enabled.
313/// 'CATEGORY' must be a null-terminated string of a type convertible to
314/// 'const char *'. If the default metrics manager has not been
315/// initialized, or if the indicated 'CATEGORY' is currently disabled,
316/// the following statement is not executed (i.e., the 'if'-condition
317/// is 'false'). This macro maintains a (function-scope static) cache
318/// containing the identity of the category. This cache is initialized
319/// using the 'CATEGORY' specified on the *first* application of this
320/// macro at a particular instantiation point; subsequent applications
321/// use that cached information, which in practice means that
322/// 'CATEGORY' must be a *runtime* *constant*. *WARNING*: although the
323/// 'BALM_METRICS_IF_CATEGORY_ENABLED' may look like a function call,
324/// it actually consists of a declaration and an 'if' statement, which
325/// means that the following is syntactically *incorrect*:
326/// 'if (BALM_METRICS_IF_CATEGORY_ENABLED("myCategory")) { stuff() }'.
327/// That should instead be written as:
328/// 'BALM_METRICS_IF_CATEGORY_ENABLED("myCategory") { stuff(); }'.
329/// @endcode
330/// Finally, this component provides a set of macros to record the elapsed wall
331/// time of a block of code:
332/// @code
333/// BALM_METRICS_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS)
334/// Update the indicated metric, identified by the specified 'CATEGORY'
335/// and 'METRIC' names, by the elapsed (wall) time, in the specified
336/// 'TIME_UNITS', from the point of instantiation of the macro to the end
337/// of the enclosing lexical scope. 'CATEGORY' and 'METRIC' must be
338/// null-terminated strings of a type convertible to 'const char *',
339/// while 'TIME_UNITS' is assumed to be of a type convertible to the
340/// enumerated type 'balm::StopwatchScopedGuard::Units'. This macro
341/// maintains a (function-scope static) cache containing the identity of
342/// the metric being updated. This cache is initialized using the
343/// 'CATEGORY' and 'METRIC' specified on the *first* application of this
344/// macro at a particular instantiation point; subsequent applications
345/// use that cached information, which in practice means that
346/// 'CATEGORY' and 'METRIC' must be *runtime* *constants*. If the
347/// default metrics manager has not been initialized, or the identified
348/// 'CATEGORY' is disabled, this macro has no effect. Note that
349/// 'TIME_UNITS' indicates the scale of value to report, but does *not*
350/// affect the precision of the elapsed time measurement.
351///
352/// BALM_METRICS_TIME_BLOCK_SECONDS(CATEGORY, METRIC)
353/// The behavior of this macro is logically equivalent to
354/// 'BALM_METRICS_TIME_BLOCK' called with
355/// 'balm::StopwatchScopedGuard::k_SECONDS'.
356///
357/// BALM_METRICS_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC)
358/// The behavior of this macro is logically equivalent to
359/// 'BALM_METRICS_TIME_BLOCK' called with
360/// 'balm::StopwatchScopedGuard::k_MILLISECONDS'.
361///
362/// BALM_METRICS_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC)
363/// The behavior of this macro is logically equivalent to
364/// 'BALM_METRICS_TIME_BLOCK' called with
365/// 'balm::StopwatchScopedGuard::k_MICROSECONDS'.
366///
367/// BALM_METRICS_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC)
368/// The behavior of this macro is logically equivalent to
369/// 'BALM_METRICS_TIME_BLOCK' called with
370/// 'balm::StopwatchScopedGuard::k_NANOSECONDS'.
371///
372/// BALM_METRICS_DYNAMIC_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS)
373/// Update the indicated metric, identified by the specified 'CATEGORY'
374/// and 'METRIC' names, by the elapsed (wall) time, in the specified
375/// 'TIME_UNITS', from the instantiation of the macro to the end of the
376/// enclosing lexical scope. 'CATEGORY' and 'METRIC' must be
377/// null-terminated strings of a type convertible to 'const char *',
378/// while 'TIME_UNITS' is assumed to be of a type convertible to the
379/// enumerated type 'balm::StopwatchScopedGuard::Units'. If the default
380/// metrics manager has not been initialized, or the identified
381/// 'CATEGORY' is disabled, this macro has no effect. Note that
382/// this operation looks up the 'CATEGORY' and 'METRIC' on *each*
383/// application, resulting in (unnecessary) additional runtime overhead
384/// (if the 'CATEGORY' and 'METRIC' values are always the same for a
385/// particular point of call). Also note that 'TIME_UNITS' indicates the
386/// scale of value to report, but does *not* affect the precision of the
387/// elapsed time measurement.
388///
389/// BALM_METRICS_DYNAMIC_TIME_BLOCK_SECONDS(CATEGORY, METRIC)
390/// The behavior of this macro is logically equivalent to
391/// 'BALM_METRICS_DYNAMIC_TIME_BLOCK' called with
392/// 'balm::StopwatchScopedGuard::k_SECONDS'.
393///
394/// BALM_METRICS_DYNAMIC_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC)
395/// The behavior of this macro is logically equivalent to
396/// 'BALM_METRICS_DYNAMIC_TIME_BLOCK' called with
397/// 'balm::StopwatchScopedGuard::k_MILLISECONDS'.
398///
399/// BALM_METRICS_DYNAMIC_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC)
400/// The behavior of this macro is logically equivalent to
401/// 'BALM_METRICS_DYNAMIC_TIME_BLOCK' called with
402/// 'balm::StopwatchScopedGuard::k_MICROSECONDS'.
403///
404/// BALM_METRICS_DYNAMIC_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC)
405/// The behavior of this macro is logically equivalent to
406/// 'BALM_METRICS_DYNAMIC_TIME_BLOCK' called with
407/// 'balm::StopwatchScopedGuard::k_NANOSECONDS'.
408/// @endcode
409///
410/// ## Usage {#balm_metrics-usage}
411///
412///
413/// This section illustrates intended use of this component.
414///
415/// ### Example 1: Create and Configure the Default balm::MetricsManager Instance {#balm_metrics-example-1-create-and-configure-the-default-balm-metricsmanager-instance}
416///
417///
418/// This example demonstrates how to create the default `balm::MetricsManager`
419/// instance and perform a trivial configuration.
420///
421/// First we create a `balm::DefaultMetricsManagerScopedGuard`, which manages
422/// the lifetime of the default metrics manager instance. At construction, we
423/// provide this guard with an output stream (`stdout`) to which the default
424/// metrics manager will publish metrics. Note that the default metrics
425/// manager is intended to be created and destroyed by the *owner* of `main`:
426/// An instance of the manager should be created during the initialization of
427/// an application (while the task has a single thread) and destroyed just
428/// prior to termination (when there is similarly a single thread).
429/// @code
430/// int main(int argc, char *argv[])
431/// {
432/// // ...
433///
434/// balm::DefaultMetricsManagerScopedGuard managerGuard(bsl::cout);
435/// @endcode
436/// Once the default manager object has been created, it can be accessed using
437/// the `instance` operation.
438/// @code
439/// balm::MetricsManager *manager =
440/// balm::DefaultMetricsManager::instance();
441/// assert(0 != manager);
442/// @endcode
443/// Note that the default metrics manager will be released when the
444/// `managerGuard` exits this scoped and is destroyed. Clients that choose to
445/// explicitly call `balm::DefaultMetricsManager::create()` must also explicitly
446/// call `balm::DefaultMetricsManager::release()`.
447///
448/// ### Example 2: Updating a Metric {#balm_metrics-example-2-updating-a-metric}
449///
450///
451/// Once a metrics manager is initialized, we can use the various macros to
452/// record metric values. In this second example, we collect metrics from a
453/// hypothetical event-processing function. We use `BALM_METRICS_UPDATE` to
454/// record the size of the data being processed to a metric named "msgSize",
455/// and the elapsed time (in milliseconds) to process the event to a metric
456/// named "elapsedTime". Finally, we use `BALM_METRICS_INCREMENT` to record a
457/// count of failures to a metric named "failureCount". Note that we do not use
458/// the `*_DYNAMIC_*` variants of the `BALM_METRICS_UPDATE` or
459/// `BALM_METRICS_INCREMENT` macros because the category and metric names are
460/// constant across all applications of the macro at a particular instantiation
461/// point (the `DYNAMIC` variants look up the category and metric name on each
462/// application, which would incur unnecessary runtime overhead).
463/// @code
464/// int processEvent(int eventId, const bsl::string& eventMessage)
465/// // Process the event described by the specified 'eventId' and
466/// // 'eventMessage'. Return 0 on success, and a non-zero
467/// // value otherwise.
468/// {
469/// (void)eventId;
470///
471/// int returnCode = 0;
472///
473/// BALM_METRICS_UPDATE("processEvent",
474/// "msgSize",
475/// static_cast<double>(eventMessage.size()));
476/// BALM_METRICS_TIME_BLOCK_MILLISECONDS("processingEvent", "elapsedTime");
477///
478/// // Process 'data'.
479///
480/// if (0 != returnCode) {
481/// BALM_METRICS_INCREMENT("processEvent", "failureCount");
482/// }
483///
484/// return returnCode;
485/// }
486/// @endcode
487///
488/// ### Example 3: Using BALM_METRICS_IF_CATEGORY_ENABLED {#balm_metrics-example-3-using-balm_metrics_if_category_enabled}
489///
490///
491/// In this next example, we use `BALM_METRICS_IF_CATEGORY_ENABLED` to
492/// conditionally disable a (relatively) expensive operation involved in
493/// computing a metric value. The `processEvent2` function, defined below, uses
494/// a `bsls::Stopwatch` to record the elapsed system, user, and wall times,
495/// associated with processing the event. The system calls used (via
496/// `bsls::Stopwatch`) to record the elapsed time may be relatively expensive,
497/// so we use `BALM_METRICS_IF_CATEGORY_ENABLED` to ensure we perform those
498/// operations only if metrics collection is enabled. Finally, we use
499/// `BALM_METRICS_UPDATE3` to update the three metrics, which is (slightly) more
500/// efficient than updating each metric individually using `BALM_METRIC_UPDATE`.
501/// @code
502/// int processEvent2(int eventId, const bsl::string& eventMessage)
503/// // Process the event described by the specified 'eventId' and
504/// // 'eventMessage'. Return 0 on success, and a non-zero
505/// // value otherwise.
506/// {
507/// (void)eventId;
508/// (void)eventMessage;
509///
510/// int returnCode = 0;
511///
512/// bsls::Stopwatch stopwatch;
513/// BALM_METRICS_IF_CATEGORY_ENABLED("processEvent2") {
514/// stopwatch.start(true);
515/// }
516///
517/// // Process 'data'.
518///
519/// BALM_METRICS_IF_CATEGORY_ENABLED("processEvent2") {
520/// double systemTime, userTime, wallTime;
521/// stopwatch.accumulatedTimes(&systemTime, &userTime, &wallTime);
522/// BALM_METRICS_UPDATE3("processEvent2",
523/// "systemTime", systemTime,
524/// "userTime", userTime,
525/// "wallTime", wallTime);
526/// }
527///
528/// return returnCode;
529/// }
530/// @endcode
531/// @}
532/** @} */
533/** @} */
534
535/** @addtogroup bal
536 * @{
537 */
538/** @addtogroup balm
539 * @{
540 */
541/** @addtogroup balm_metrics
542 * @{
543 */
544
545#include <balscm_version.h>
546
547#include <balm_category.h>
548#include <balm_collector.h>
552#include <balm_metricid.h>
553#include <balm_metricregistry.h>
554#include <balm_metricsmanager.h>
555#include <balm_publicationtype.h>
557
558#include <bsls_performancehint.h>
559#include <bsls_platform.h>
560
561 // ================================
562 // BALM_METRICS_IF_CATEGORY_ENABLED
563 // ================================
564
565#define BALM_METRICS_IF_CATEGORY_ENABLED(CATEGORY) \
566 BALM_METRICS_IF_CATEGORY_ENABLED_IMP( \
567 CATEGORY, BALM_METRICS_UNIQUE_NAME(categoryHolder))
568
569 // ===================
570 // BALM_METRICS_UPDATE
571 // ===================
572
573// Note that the static collector address must be assigned *before*
574// initializing category holder to ensure initialization is thread safe.
575#define BALM_METRICS_UPDATE(CATEGORY, METRIC1, VALUE1) do { \
576 using namespace BloombergLP; \
577 typedef balm::Metrics_Helper Helper; \
578 static balm::CategoryHolder holder = { false, 0, 0 }; \
579 static balm::Collector *collector1 = 0; \
580 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
581 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
582 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
583 collector1 = Helper::getCollector(CATEGORY, METRIC1); \
584 Helper::initializeCategoryHolder(&holder, CATEGORY); \
585 } \
586 if (holder.enabled()) { \
587 collector1->update(VALUE1); \
588 } \
589 } while (0)
590
591#define BALM_METRICS_UPDATE2(CATEGORY, METRIC1, VALUE1, METRIC2, VALUE2) do { \
592 using namespace BloombergLP; \
593 typedef balm::Metrics_Helper Helper; \
594 static balm::CategoryHolder holder = { false, 0, 0 }; \
595 static balm::Collector *collector1 = 0; \
596 static balm::Collector *collector2 = 0; \
597 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
598 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
599 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
600 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
601 collector1 = Helper::getCollector(CATEGORY, METRIC1); \
602 collector2 = Helper::getCollector(CATEGORY, METRIC2); \
603 Helper::initializeCategoryHolder(&holder, CATEGORY); \
604 } \
605 if (holder.enabled()) { \
606 collector1->update(VALUE1); \
607 collector2->update(VALUE2); \
608 } \
609 } while (0)
610
611#define BALM_METRICS_UPDATE3(CATEGORY, \
612 METRIC1, \
613 VALUE1, \
614 METRIC2, \
615 VALUE2, \
616 METRIC3, \
617 VALUE3) do { \
618 using namespace BloombergLP; \
619 typedef balm::Metrics_Helper Helper; \
620 static balm::CategoryHolder holder = { false, 0, 0 }; \
621 static balm::Collector *collector1 = 0; \
622 static balm::Collector *collector2 = 0; \
623 static balm::Collector *collector3 = 0; \
624 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
625 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
626 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
627 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
628 Helper::logEmptyName(METRIC3, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
629 collector1 = Helper::getCollector(CATEGORY, METRIC1); \
630 collector2 = Helper::getCollector(CATEGORY, METRIC2); \
631 collector3 = Helper::getCollector(CATEGORY, METRIC3); \
632 Helper::initializeCategoryHolder(&holder, CATEGORY); \
633 } \
634 if (holder.enabled()) { \
635 collector1->update(VALUE1); \
636 collector2->update(VALUE2); \
637 collector3->update(VALUE3); \
638 } \
639 } while (0)
640
641#define BALM_METRICS_UPDATE4(CATEGORY, \
642 METRIC1, \
643 VALUE1, \
644 METRIC2, \
645 VALUE2, \
646 METRIC3, \
647 VALUE3, \
648 METRIC4, \
649 VALUE4) do { \
650 using namespace BloombergLP; \
651 typedef balm::Metrics_Helper Helper; \
652 static balm::CategoryHolder holder = { false, 0, 0 }; \
653 static balm::Collector *collector1 = 0; \
654 static balm::Collector *collector2 = 0; \
655 static balm::Collector *collector3 = 0; \
656 static balm::Collector *collector4 = 0; \
657 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
658 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
659 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
660 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
661 Helper::logEmptyName(METRIC3, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
662 Helper::logEmptyName(METRIC4, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
663 collector1 = Helper::getCollector(CATEGORY, METRIC1); \
664 collector2 = Helper::getCollector(CATEGORY, METRIC2); \
665 collector3 = Helper::getCollector(CATEGORY, METRIC3); \
666 collector4 = Helper::getCollector(CATEGORY, METRIC4); \
667 Helper::initializeCategoryHolder(&holder, CATEGORY); \
668 } \
669 if (holder.enabled()) { \
670 collector1->update(VALUE1); \
671 collector2->update(VALUE2); \
672 collector3->update(VALUE3); \
673 collector4->update(VALUE4); \
674 } \
675 } while (0)
676
677#define BALM_METRICS_UPDATE5(CATEGORY, \
678 METRIC1, \
679 VALUE1, \
680 METRIC2, \
681 VALUE2, \
682 METRIC3, \
683 VALUE3, \
684 METRIC4, \
685 VALUE4, \
686 METRIC5, \
687 VALUE5) do { \
688 using namespace BloombergLP; \
689 typedef balm::Metrics_Helper Helper; \
690 static balm::CategoryHolder holder = { false, 0, 0 }; \
691 static balm::Collector *collector1 = 0; \
692 static balm::Collector *collector2 = 0; \
693 static balm::Collector *collector3 = 0; \
694 static balm::Collector *collector4 = 0; \
695 static balm::Collector *collector5 = 0; \
696 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
697 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
698 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
699 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
700 Helper::logEmptyName(METRIC3, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
701 Helper::logEmptyName(METRIC4, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
702 Helper::logEmptyName(METRIC5, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
703 collector1 = Helper::getCollector(CATEGORY, METRIC1); \
704 collector2 = Helper::getCollector(CATEGORY, METRIC2); \
705 collector3 = Helper::getCollector(CATEGORY, METRIC3); \
706 collector4 = Helper::getCollector(CATEGORY, METRIC4); \
707 collector5 = Helper::getCollector(CATEGORY, METRIC5); \
708 Helper::initializeCategoryHolder(&holder, CATEGORY); \
709 } \
710 if (holder.enabled()) { \
711 collector1->update(VALUE1); \
712 collector2->update(VALUE2); \
713 collector3->update(VALUE3); \
714 collector4->update(VALUE4); \
715 collector5->update(VALUE5); \
716 } \
717 } while (0)
718
719#define BALM_METRICS_UPDATE6(CATEGORY, \
720 METRIC1, \
721 VALUE1, \
722 METRIC2, \
723 VALUE2, \
724 METRIC3, \
725 VALUE3, \
726 METRIC4, \
727 VALUE4, \
728 METRIC5, \
729 VALUE5, \
730 METRIC6, \
731 VALUE6) do { \
732 using namespace BloombergLP; \
733 typedef balm::Metrics_Helper Helper; \
734 static balm::CategoryHolder holder = { false, 0, 0 }; \
735 static balm::Collector *collector1 = 0; \
736 static balm::Collector *collector2 = 0; \
737 static balm::Collector *collector3 = 0; \
738 static balm::Collector *collector4 = 0; \
739 static balm::Collector *collector5 = 0; \
740 static balm::Collector *collector6 = 0; \
741 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
742 Helper::logEmptyName(CATEGORY, Helper::e_TYPE_CATEGORY, \
743 __FILE__, __LINE__); \
744 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
745 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
746 Helper::logEmptyName(METRIC3, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
747 Helper::logEmptyName(METRIC4, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
748 Helper::logEmptyName(METRIC5, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
749 Helper::logEmptyName(METRIC6, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
750 collector1 = Helper::getCollector(CATEGORY, METRIC1); \
751 collector2 = Helper::getCollector(CATEGORY, METRIC2); \
752 collector3 = Helper::getCollector(CATEGORY, METRIC3); \
753 collector4 = Helper::getCollector(CATEGORY, METRIC4); \
754 collector5 = Helper::getCollector(CATEGORY, METRIC5); \
755 collector6 = Helper::getCollector(CATEGORY, METRIC6); \
756 Helper::initializeCategoryHolder(&holder, CATEGORY); \
757 } \
758 if (holder.enabled()) { \
759 collector1->update(VALUE1); \
760 collector2->update(VALUE2); \
761 collector3->update(VALUE3); \
762 collector4->update(VALUE4); \
763 collector5->update(VALUE5); \
764 collector6->update(VALUE6); \
765 } \
766 } while (0)
767
768#define BALM_METRICS_TYPED_UPDATE(CATEGORY, METRIC, VALUE, PREFERRED_TYPE) \
769 do { \
770 using namespace BloombergLP; \
771 typedef balm::Metrics_Helper Helper; \
772 static balm::CategoryHolder holder = { false, 0, 0 }; \
773 static balm::Collector *collector1 = 0; \
774 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
775 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
776 Helper::logEmptyName(METRIC, Helper::e_TYPE_METRIC, __FILE__, __LINE__); \
777 collector1 = Helper::getCollector(CATEGORY, METRIC); \
778 Helper::setPublicationType(collector1->metricId(), PREFERRED_TYPE); \
779 Helper::initializeCategoryHolder(&holder, CATEGORY); \
780 } \
781 if (holder.enabled()) { \
782 collector1->update(VALUE); \
783 } \
784 } while (0)
785
786#define BALM_METRICS_DYNAMIC_UPDATE(CATEGORY, METRIC, VALUE) do { \
787 using namespace BloombergLP; \
788 if (balm::DefaultMetricsManager::instance()) { \
789 balm::CollectorRepository& repository = \
790 balm::DefaultMetricsManager::instance()->collectorRepository(); \
791 balm::Collector *collector = repository.getDefaultCollector( \
792 (CATEGORY), (METRIC));\
793 if (collector->metricId().category()->enabled()) { \
794 collector->update((VALUE)); \
795 } \
796 } \
797 } while(0)
798
799 // =======================
800 // BALM_METRICS_INT_UPDATE
801 // =======================
802
803#define BALM_METRICS_INT_UPDATE(CATEGORY, METRIC1, VALUE1) do { \
804 using namespace BloombergLP; \
805 typedef balm::Metrics_Helper Helper; \
806 static balm::CategoryHolder holder = { false, 0, 0 }; \
807 static balm::IntegerCollector *collector1 = 0; \
808 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
809 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
810 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
811 collector1 = Helper::getIntegerCollector(CATEGORY, METRIC1); \
812 Helper::initializeCategoryHolder(&holder, CATEGORY); \
813 } \
814 if (holder.enabled()) { \
815 collector1->update(VALUE1); \
816 } \
817 } while (0)
818
819#define BALM_METRICS_INT_UPDATE2(CATEGORY, \
820 METRIC1, \
821 VALUE1, \
822 METRIC2, \
823 VALUE2) do { \
824 using namespace BloombergLP; \
825 typedef balm::Metrics_Helper Helper; \
826 static balm::CategoryHolder holder = { false, 0, 0 }; \
827 static balm::IntegerCollector *collector1 = 0; \
828 static balm::IntegerCollector *collector2 = 0; \
829 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
830 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
831 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
832 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
833 collector1 = Helper::getIntegerCollector(CATEGORY, METRIC1); \
834 collector2 = Helper::getIntegerCollector(CATEGORY, METRIC2); \
835 Helper::initializeCategoryHolder(&holder, CATEGORY); \
836 } \
837 if (holder.enabled()) { \
838 collector1->update(VALUE1); \
839 collector2->update(VALUE2); \
840 } \
841 } while (0)
842
843#define BALM_METRICS_INT_UPDATE3(CATEGORY, \
844 METRIC1, \
845 VALUE1, \
846 METRIC2, \
847 VALUE2, \
848 METRIC3, \
849 VALUE3) do { \
850 using namespace BloombergLP; \
851 typedef balm::Metrics_Helper Helper; \
852 static balm::CategoryHolder holder = { false, 0, 0 }; \
853 static balm::IntegerCollector *collector1 = 0; \
854 static balm::IntegerCollector *collector2 = 0; \
855 static balm::IntegerCollector *collector3 = 0; \
856 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
857 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
858 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
859 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
860 Helper::logEmptyName(METRIC3, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
861 collector1 = Helper::getIntegerCollector(CATEGORY, METRIC1); \
862 collector2 = Helper::getIntegerCollector(CATEGORY, METRIC2); \
863 collector3 = Helper::getIntegerCollector(CATEGORY, METRIC3); \
864 Helper::initializeCategoryHolder(&holder, CATEGORY); \
865 } \
866 if (holder.enabled()) { \
867 collector1->update(VALUE1); \
868 collector2->update(VALUE2); \
869 collector3->update(VALUE3); \
870 } \
871 } while (0)
872
873#define BALM_METRICS_INT_UPDATE4(CATEGORY, \
874 METRIC1, \
875 VALUE1, \
876 METRIC2, \
877 VALUE2, \
878 METRIC3, \
879 VALUE3, \
880 METRIC4, \
881 VALUE4) do { \
882 using namespace BloombergLP; \
883 typedef balm::Metrics_Helper Helper; \
884 static balm::CategoryHolder holder = { false, 0, 0 }; \
885 static balm::IntegerCollector *collector1 = 0; \
886 static balm::IntegerCollector *collector2 = 0; \
887 static balm::IntegerCollector *collector3 = 0; \
888 static balm::IntegerCollector *collector4 = 0; \
889 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
890 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
891 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
892 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
893 Helper::logEmptyName(METRIC3, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
894 Helper::logEmptyName(METRIC4, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
895 collector1 = Helper::getIntegerCollector(CATEGORY, METRIC1); \
896 collector2 = Helper::getIntegerCollector(CATEGORY, METRIC2); \
897 collector3 = Helper::getIntegerCollector(CATEGORY, METRIC3); \
898 collector4 = Helper::getIntegerCollector(CATEGORY, METRIC4); \
899 Helper::initializeCategoryHolder(&holder, CATEGORY); \
900 } \
901 if (holder.enabled()) { \
902 collector1->update(VALUE1); \
903 collector2->update(VALUE2); \
904 collector3->update(VALUE3); \
905 collector4->update(VALUE4); \
906 } \
907 } while (0)
908
909#define BALM_METRICS_INT_UPDATE5(CATEGORY, \
910 METRIC1, \
911 VALUE1, \
912 METRIC2, \
913 VALUE2, \
914 METRIC3, \
915 VALUE3, \
916 METRIC4, \
917 VALUE4, \
918 METRIC5, \
919 VALUE5) do { \
920 using namespace BloombergLP; \
921 typedef balm::Metrics_Helper Helper; \
922 static balm::CategoryHolder holder = { false, 0, 0 }; \
923 static balm::IntegerCollector *collector1 = 0; \
924 static balm::IntegerCollector *collector2 = 0; \
925 static balm::IntegerCollector *collector3 = 0; \
926 static balm::IntegerCollector *collector4 = 0; \
927 static balm::IntegerCollector *collector5 = 0; \
928 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
929 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
930 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
931 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
932 Helper::logEmptyName(METRIC3, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
933 Helper::logEmptyName(METRIC4, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
934 Helper::logEmptyName(METRIC5, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
935 collector1 = Helper::getIntegerCollector(CATEGORY, METRIC1); \
936 collector2 = Helper::getIntegerCollector(CATEGORY, METRIC2); \
937 collector3 = Helper::getIntegerCollector(CATEGORY, METRIC3); \
938 collector4 = Helper::getIntegerCollector(CATEGORY, METRIC4); \
939 collector5 = Helper::getIntegerCollector(CATEGORY, METRIC5); \
940 Helper::initializeCategoryHolder(&holder, CATEGORY); \
941 } \
942 if (holder.enabled()) { \
943 collector1->update(VALUE1); \
944 collector2->update(VALUE2); \
945 collector3->update(VALUE3); \
946 collector4->update(VALUE4); \
947 collector5->update(VALUE5); \
948 } \
949 } while (0)
950
951#define BALM_METRICS_INT_UPDATE6(CATEGORY, \
952 METRIC1, \
953 VALUE1, \
954 METRIC2, \
955 VALUE2, \
956 METRIC3, \
957 VALUE3, \
958 METRIC4, \
959 VALUE4, \
960 METRIC5, \
961 VALUE5, \
962 METRIC6, \
963 VALUE6) do { \
964 using namespace BloombergLP; \
965 typedef balm::Metrics_Helper Helper; \
966 static balm::CategoryHolder holder = { false, 0, 0 }; \
967 static balm::IntegerCollector *collector1 = 0; \
968 static balm::IntegerCollector *collector2 = 0; \
969 static balm::IntegerCollector *collector3 = 0; \
970 static balm::IntegerCollector *collector4 = 0; \
971 static balm::IntegerCollector *collector5 = 0; \
972 static balm::IntegerCollector *collector6 = 0; \
973 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
974 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
975 Helper::logEmptyName(METRIC1, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
976 Helper::logEmptyName(METRIC2, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
977 Helper::logEmptyName(METRIC3, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
978 Helper::logEmptyName(METRIC4, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
979 Helper::logEmptyName(METRIC5, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
980 Helper::logEmptyName(METRIC6, Helper::e_TYPE_METRIC, __FILE__, __LINE__);\
981 collector1 = Helper::getIntegerCollector(CATEGORY, METRIC1); \
982 collector2 = Helper::getIntegerCollector(CATEGORY, METRIC2); \
983 collector3 = Helper::getIntegerCollector(CATEGORY, METRIC3); \
984 collector4 = Helper::getIntegerCollector(CATEGORY, METRIC4); \
985 collector5 = Helper::getIntegerCollector(CATEGORY, METRIC5); \
986 collector6 = Helper::getIntegerCollector(CATEGORY, METRIC6); \
987 Helper::initializeCategoryHolder(&holder, CATEGORY); \
988 } \
989 if (holder.enabled()) { \
990 collector1->update(VALUE1); \
991 collector2->update(VALUE2); \
992 collector3->update(VALUE3); \
993 collector4->update(VALUE4); \
994 collector5->update(VALUE5); \
995 collector6->update(VALUE6); \
996 } \
997 } while (0)
998
999#define BALM_METRICS_TYPED_INT_UPDATE(CATEGORY, \
1000 METRIC, \
1001 VALUE, \
1002 PREFERRED_TYPE) \
1003do { \
1004 using namespace BloombergLP; \
1005 typedef balm::Metrics_Helper Helper; \
1006 static balm::CategoryHolder holder = { false, 0, 0 }; \
1007 static balm::IntegerCollector *collector1 = 0; \
1008 if (0 == holder.category() && balm::DefaultMetricsManager::instance()) { \
1009 Helper::logEmptyName(CATEGORY,Helper::e_TYPE_CATEGORY,__FILE__,__LINE__);\
1010 Helper::logEmptyName(METRIC, Helper::e_TYPE_METRIC, __FILE__, __LINE__); \
1011 collector1 = Helper::getIntegerCollector(CATEGORY, METRIC); \
1012 Helper::setPublicationType(collector1->metricId(), PREFERRED_TYPE); \
1013 Helper::initializeCategoryHolder(&holder, CATEGORY); \
1014 } \
1015 if (holder.enabled()) { \
1016 collector1->update(VALUE); \
1017 } \
1018 } while (0)
1019
1020#define BALM_METRICS_DYNAMIC_INT_UPDATE(CATEGORY, METRIC, VALUE) do { \
1021 using namespace BloombergLP; \
1022 if (balm::DefaultMetricsManager::instance()) { \
1023 balm::CollectorRepository& repository = \
1024 balm::DefaultMetricsManager::instance()->collectorRepository(); \
1025 balm::IntegerCollector *collector = \
1026 repository.getDefaultIntegerCollector((CATEGORY), (METRIC)); \
1027 if (collector->metricId().category()->enabled()) { \
1028 collector->update((VALUE)); \
1029 } \
1030 } \
1031 } while (0)
1032
1033#define BALM_METRICS_INCREMENT(CATEGORY, METRIC) \
1034 BALM_METRICS_INT_UPDATE(CATEGORY, METRIC, 1)
1035
1036#define BALM_METRICS_TYPED_INCREMENT(CATEGORY, METRIC, PREFERRED_TYPE) \
1037 BALM_METRICS_TYPED_INT_UPDATE(CATEGORY, METRIC, 1, PREFERRED_TYPE)
1038
1039#define BALM_METRICS_DYNAMIC_INCREMENT(CATEGORY, METRIC) \
1040 BALM_METRICS_DYNAMIC_INT_UPDATE(CATEGORY, METRIC, 1)
1041
1042 // =======================
1043 // BALM_METRICS_TIME_BLOCK
1044 // =======================
1045
1046#define BALM_METRICS_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS) \
1047 BALM_METRICS_TIME_BLOCK_IMP((CATEGORY), \
1048 (METRIC), \
1049 TIME_UNITS, \
1050 BALM_METRICS_UNIQUE_NAME(_bAlM_CoLlEcToR))
1051
1052#define BALM_METRICS_DYNAMIC_TIME_BLOCK(CATEGORY, METRIC, TIME_UNITS) \
1053 BALM_METRICS_DYNAMIC_TIME_BLOCK_IMP( \
1054 (CATEGORY), \
1055 (METRIC), \
1056 TIME_UNITS, \
1057 BALM_METRICS_UNIQUE_NAME(_bAlM_CoLlEcToR))
1058
1059#define BALM_METRICS_TIME_BLOCK_SECONDS(CATEGORY, METRIC) \
1060 BALM_METRICS_TIME_BLOCK((CATEGORY), \
1061 (METRIC), \
1062 BloombergLP::balm::StopwatchScopedGuard::k_SECONDS);
1063
1064#define BALM_METRICS_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC) \
1065 BALM_METRICS_TIME_BLOCK( \
1066 (CATEGORY), \
1067 (METRIC), \
1068 BloombergLP::balm::StopwatchScopedGuard::k_MILLISECONDS);
1069
1070#define BALM_METRICS_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC) \
1071 BALM_METRICS_TIME_BLOCK( \
1072 (CATEGORY), \
1073 (METRIC), \
1074 BloombergLP::balm::StopwatchScopedGuard::k_MICROSECONDS);
1075
1076#define BALM_METRICS_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC) \
1077 BALM_METRICS_TIME_BLOCK( \
1078 (CATEGORY), \
1079 (METRIC), \
1080 BloombergLP::balm::StopwatchScopedGuard::k_NANOSECONDS);
1081
1082#define BALM_METRICS_DYNAMIC_TIME_BLOCK_SECONDS(CATEGORY, METRIC) \
1083 BALM_METRICS_DYNAMIC_TIME_BLOCK( \
1084 (CATEGORY), \
1085 (METRIC), \
1086 BloombergLP::balm::StopwatchScopedGuard::k_SECONDS);
1087
1088#define BALM_METRICS_DYNAMIC_TIME_BLOCK_MILLISECONDS(CATEGORY, METRIC) \
1089 BALM_METRICS_DYNAMIC_TIME_BLOCK( \
1090 (CATEGORY), \
1091 (METRIC), \
1092 BloombergLP::balm::StopwatchScopedGuard::k_MILLISECONDS);
1093
1094#define BALM_METRICS_DYNAMIC_TIME_BLOCK_MICROSECONDS(CATEGORY, METRIC) \
1095 BALM_METRICS_DYNAMIC_TIME_BLOCK( \
1096 (CATEGORY), \
1097 (METRIC), \
1098 BloombergLP::balm::StopwatchScopedGuard::k_MICROSECONDS);
1099
1100#define BALM_METRICS_DYNAMIC_TIME_BLOCK_NANOSECONDS(CATEGORY, METRIC) \
1101 BALM_METRICS_DYNAMIC_TIME_BLOCK( \
1102 (CATEGORY), \
1103 (METRIC), \
1104 BloombergLP::balm::StopwatchScopedGuard::k_NANOSECONDS);
1105
1106 // =====================
1107 // Macro Implementations
1108 // =====================
1109
1110#define BALM_METRICS_IF_CATEGORY_ENABLED_IMP(CATEGORY, HOLDER_NAME) \
1111 static BloombergLP::balm::CategoryHolder HOLDER_NAME = { false, 0, 0 }; \
1112 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!HOLDER_NAME.category()) \
1113 && BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY( \
1114 BloombergLP::balm::DefaultMetricsManager::instance() != 0)) {\
1115 BloombergLP::balm::Metrics_Helper::initializeCategoryHolder( \
1116 &HOLDER_NAME, CATEGORY); \
1117 } \
1118 if (HOLDER_NAME.enabled())
1119
1120// Declare a static pointer to a 'balm::Collector' with the specified
1121// 'VARIABLE_NAME' and an initial value of 0. If the default metrics manager
1122// is available and the declared pointer variable (named 'VARIABLE_NAME') is 0,
1123// assign to 'VARIABLE_NAME' the address of a collector for the specified
1124// 'CATEGORY' and 'METRIC'. Finally, declare a 'balm::StopwatchScopedGuard'
1125// object with a unique variable name and supply its constructor the collector
1126// address held in 'VARIABLE_NAME' and the specified 'TIME_UNITS'.
1127#define BALM_METRICS_TIME_BLOCK_IMP(CATEGORY, \
1128 METRIC, \
1129 TIME_UNITS, \
1130 VARIABLE_NAME) \
1131 static BloombergLP::balm::Collector *VARIABLE_NAME = 0; \
1132 if (BloombergLP::balm::DefaultMetricsManager::instance()) { \
1133 using namespace BloombergLP; \
1134 typedef balm::Metrics_Helper Helper; \
1135 static balm::CategoryHolder holder = { false, 0, 0 }; \
1136 if (0 == holder.category()) { \
1137 balm::CollectorRepository& repository = \
1138 balm::DefaultMetricsManager::instance()->collectorRepository(); \
1139 VARIABLE_NAME = repository.getDefaultCollector((CATEGORY), \
1140 (METRIC)); \
1141 Helper::initializeCategoryHolder(&holder, CATEGORY); \
1142 } \
1143 } \
1144 else { \
1145 VARIABLE_NAME = 0; \
1146 } \
1147 BloombergLP::balm::StopwatchScopedGuard \
1148 BALM_METRICS_UNIQUE_NAME(__bAlM_gUaRd)(VARIABLE_NAME, TIME_UNITS);
1149
1150// Declare a pointer to a 'balm::Collector' with the specified 'VARIABLE_NAME'.
1151// If the default metrics manager is available, assign to the declared pointer
1152// variable (named 'VARIABLE_NAME') the address of a collector for the
1153// specified 'CATEGORY' and 'METRIC'. Finally, declare a
1154// 'balm::StopwatchScopedGuard' object with a unique variable name and supply
1155// its constructor the collector address held in 'VARIABLE_NAME' and the
1156// specified 'TIME_UNITS'.
1157#define BALM_METRICS_DYNAMIC_TIME_BLOCK_IMP(CATEGORY, \
1158 METRIC, \
1159 TIME_UNITS, \
1160 VARIABLE_NAME) \
1161 BloombergLP::balm::Collector *VARIABLE_NAME = 0; \
1162 if (BloombergLP::balm::DefaultMetricsManager::instance()) { \
1163 using namespace BloombergLP; \
1164 balm::CollectorRepository& repository = \
1165 balm::DefaultMetricsManager::instance()->collectorRepository(); \
1166 VARIABLE_NAME = repository.getDefaultCollector((CATEGORY), \
1167 (METRIC)); \
1168 } \
1169 BloombergLP::balm::StopwatchScopedGuard \
1170 BALM_METRICS_UNIQUE_NAME(__bAlM_gUaRd)(VARIABLE_NAME, TIME_UNITS);
1171
1172 // ------------------------
1173 // Unique line number macro
1174 // ------------------------
1175
1176#if defined(BSLS_PLATFORM_CMP_MSVC)
1177// MSVC: __LINE__ macro breaks when /ZI is used (see Q199057 or KB199057)
1178// Fortunately the __COUNTER__ extension provided by MSVC is even better.
1179# define BALM_METRICS_UNIQNUM __COUNTER__
1180#else
1181# define BALM_METRICS_UNIQNUM __LINE__
1182#endif
1183
1184 // ----------------------------------
1185 // Token concatenation support macros
1186 // ----------------------------------
1187
1188// Second layer needed to ensure that arguments are expanded before
1189// concatenation.
1190#define BALM_METRICS_CAT(X, Y) BALM_METRICS_CAT_IMP(X, Y)
1191#define BALM_METRICS_CAT_IMP(X, Y) X##Y
1192
1193 // ----------------------------------
1194 // Unique variable name support macro
1195 // ----------------------------------
1196
1197// Create a unique variable name by concatenating the specified 'X' string
1198// with a unique integer value.
1199#define BALM_METRICS_UNIQUE_NAME(X) \
1200 BALM_METRICS_CAT(X, BALM_METRICS_UNIQNUM)
1201
1202
1203
1204namespace balm {
1205 // =====================
1206 // struct Metrics_Helper
1207 // =====================
1208
1209/// This `struct` provides a namespace for a suite of functions used in the
1210/// implementation of the macros defined in this component.
1211///
1212/// This type is an implementation detail and *must* *not* be used
1213/// (directly) by clients outside of this component.
1215
1216 // TYPES
1218 // Enumeration indicating the type of identifier supplied to
1219 // 'logEmptyName'.
1220
1222 e_TYPE_METRIC = 1
1223#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1226#endif
1228
1229 // CLASS METHODS
1230
1231 /// Load into the specified `holder` the address and enabled status of
1232 /// the specified `category`, and add `holder` to the list of category
1233 /// holders for `category`. The behavior is undefined unless the balm
1234 /// metrics manager singleton is valid.
1235 static void initializeCategoryHolder(CategoryHolder *holder,
1236 const char *category);
1237
1238 /// Return the address of the default metrics collector for the metric
1239 /// identified by the specified `category` and `metric` names. The
1240 /// behavior is undefined unless the `balm` metrics manager singleton is
1241 /// valid.
1242 static Collector *getCollector(const char *category,
1243 const char *metric);
1244
1245 /// Return the address of the default integer metrics collector for the
1246 /// metric identified by the specified `category` and `metric` names.
1247 /// The behavior is undefined unless the `balm` metrics manager
1248 /// singleton is valid.
1249 static IntegerCollector *getIntegerCollector(const char *category,
1250 const char *metric);
1251
1252 /// Set the publication type for the metric identified by the specified
1253 /// `id` to the specified `type`. The behavior is undefined unless the
1254 /// `balm` metrics manager singleton is valid, and `id` is a valid
1255 /// identifier supplied by the singleton metrics manager.
1256 static void setPublicationType(const MetricId& id,
1258
1259 /// If the specified `name` is empty or contains only whitespace, then
1260 /// log a warning message indicating whether `name` is a category or a
1261 /// metric, depending on the specified `type`, and the location at which
1262 /// this function is called, indicated by the specified `file` and
1263 /// `line`; otherwise, do nothing.
1264 static void logEmptyName(const char *name,
1265 NameType type,
1266 const char *file,
1267 int line);
1268};
1269
1270// ============================================================================
1271// INLINE DEFINITIONS
1272// ============================================================================
1273
1274 // ---------------------
1275 // struct Metrics_Helper
1276 // ---------------------
1277
1278// CLASS METHODS
1279inline
1281 const char *category)
1282{
1284 MetricRegistry& registry = manager->metricRegistry();
1285 registry.registerCategoryHolder(registry.getCategory(category), holder);
1286}
1287
1288inline
1290 const char *metric)
1291{
1293 return manager->collectorRepository().getDefaultCollector(category,
1294 metric);
1295}
1296
1297inline
1299 const char *metric)
1300{
1302 return manager->collectorRepository().getDefaultIntegerCollector(category,
1303 metric);
1304}
1305
1306inline
1309{
1311 return manager->metricRegistry().setPreferredPublicationType(id, type);
1312
1313}
1314
1315} // close package namespace
1316
1317
1318#if !defined(BSL_DOUBLE_UNDERSCORE_XLAT) || 1 == BSL_DOUBLE_UNDERSCORE_XLAT
1319#define BALM_METRICS__UNIQUE_NAME(X) BALM_METRICS_UNIQUE_NAME(X)
1320#endif
1321
1322#endif
1323
1324// ----------------------------------------------------------------------------
1325// Copyright 2015 Bloomberg Finance L.P.
1326//
1327// Licensed under the Apache License, Version 2.0 (the "License");
1328// you may not use this file except in compliance with the License.
1329// You may obtain a copy of the License at
1330//
1331// http://www.apache.org/licenses/LICENSE-2.0
1332//
1333// Unless required by applicable law or agreed to in writing, software
1334// distributed under the License is distributed on an "AS IS" BASIS,
1335// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1336// See the License for the specific language governing permissions and
1337// limitations under the License.
1338// ----------------------------- END-OF-FILE ----------------------------------
1339
1340/** @} */
1341/** @} */
1342/** @} */
Definition balm_category.h:257
IntegerCollector * getDefaultIntegerCollector(const char *category, const char *metricName)
Definition balm_collectorrepository.h:444
Collector * getDefaultCollector(const char *category, const char *metricName)
Definition balm_collectorrepository.h:437
Definition balm_collector.h:152
Definition balm_integercollector.h:151
Definition balm_metricid.h:162
Definition balm_metricregistry.h:180
const Category * getCategory(const char *category)
void setPreferredPublicationType(const MetricId &metric, PublicationType::Value type)
void registerCategoryHolder(const Category *category, CategoryHolder *holder)
Definition balm_metricsmanager.h:490
CollectorRepository & collectorRepository()
Definition balm_metricsmanager.h:1013
MetricRegistry & metricRegistry()
Definition balm_metricsmanager.h:1019
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balm_bdlmmetricsadapter.h:141
static MetricsManager * instance()
Definition balm_defaultmetricsmanager.h:296
Definition balm_metrics.h:1214
static void logEmptyName(const char *name, NameType type, const char *file, int line)
static void setPublicationType(const MetricId &id, PublicationType::Value type)
Definition balm_metrics.h:1307
static Collector * getCollector(const char *category, const char *metric)
Definition balm_metrics.h:1289
NameType
Definition balm_metrics.h:1217
@ e_TYPE_CATEGORY
Definition balm_metrics.h:1221
@ e_TYPE_METRIC
Definition balm_metrics.h:1222
@ TYPE_CATEGORY
Definition balm_metrics.h:1224
@ TYPE_METRIC
Definition balm_metrics.h:1225
static void initializeCategoryHolder(CategoryHolder *holder, const char *category)
Definition balm_metrics.h:1280
static IntegerCollector * getIntegerCollector(const char *category, const char *metric)
Definition balm_metrics.h:1298
Value
Definition balm_publicationtype.h:81