BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balm_integermetric.h
Go to the documentation of this file.
1/// @file balm_integermetric.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balm_integermetric.h -*-C++-*-
8#ifndef INCLUDED_BALM_INTEGERMETRIC
9#define INCLUDED_BALM_INTEGERMETRIC
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balm_integermetric balm_integermetric
15/// @brief Provide helper classes for recording int metric values.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balm
19/// @{
20/// @addtogroup balm_integermetric
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balm_integermetric-purpose"> Purpose</a>
25/// * <a href="#balm_integermetric-classes"> Classes </a>
26/// * <a href="#balm_integermetric-description"> Description </a>
27/// * <a href="#balm_integermetric-alternative-systems-for-telemetry"> Alternative Systems for Telemetry </a>
28/// * <a href="#balm_integermetric-choosing-between-balm-integermetric-and-macros"> Choosing Between balm::IntegerMetric and Macros </a>
29/// * <a href="#balm_integermetric-thread-safety"> Thread Safety </a>
30/// * <a href="#balm_integermetric-usage"> Usage </a>
31/// * <a href="#balm_integermetric-example-1-metric-collection-with-balm-integermetric"> Example 1: Metric Collection With balm::IntegerMetric </a>
32/// * <a href="#balm_integermetric-example-2-create-and-access-the-default-balm-metricsmanager-instance"> Example 2: Create and Access the Default balm::MetricsManager Instance </a>
33///
34/// # Purpose {#balm_integermetric-purpose}
35/// Provide helper classes for recording int metric values.
36///
37/// # Classes {#balm_integermetric-classes}
38///
39/// - balm::IntegerMetric: container for recording integer metric values
40///
41/// @see balm_metric, balm_metrics, balm_metricsmanager,
42/// balm_defaultmetricsmanager
43///
44/// # Description {#balm_integermetric-description}
45/// This component provides a class, `balm::IntegerMetric`, to
46/// simplify the process of collecting integer metrics. A metric records the
47/// number of times an event occurs, as well as an associated measurement
48/// value. This component does *not* define what constitutes an event or what
49/// the associated value represents. A metric maintains a count of event
50/// occurrences and the aggregated minimum, maximum, and total of the measured
51/// metric-event values.
52///
53/// The `balm::IntegerMetric` class, defined in this component, has in-core
54/// value semantics. Each `balm::IntegerMetric` object holds a pointer to a
55/// `balm::IntegerCollector` that collects values for a particular integer
56/// metric. The `balm::IntegerCollector` is either supplied at construction, or
57/// else obtained from a `balm::MetricsManager` object's
58/// `balm::CollectorRepository`. If the supplied `balm::MetricsManager` is 0,
59/// the metric will use the default metrics manager instance
60/// (`balm::DefaultMetricsManager::instance()`), if initialized; otherwise the
61/// metric is placed in the inactive state (i.e., `isActive()` is `false`) and
62/// operations that would otherwise update the metric will have no effect.
63///
64/// ## Alternative Systems for Telemetry {#balm_integermetric-alternative-systems-for-telemetry}
65///
66///
67/// Bloomberg software may alternatively use the GUTS telemetry API, which is
68/// integrated into Bloomberg infrastructure.
69///
70/// ## Choosing Between balm::IntegerMetric and Macros {#balm_integermetric-choosing-between-balm-integermetric-and-macros}
71///
72///
73/// The `balm::IntegerMetric` class and the macros defined in @ref balm_metrics
74/// provide the same basic functionality. Clients may find
75/// `balm::IntegerMetric` objects better suited to collecting integer metrics
76/// associated with a particular instance of a stateful object, while macros are
77/// better suited to collecting metrics associated with a particular code path
78/// (rather than an object instance). In most instances choosing is a matter of
79/// taste.
80///
81/// ## Thread Safety {#balm_integermetric-thread-safety}
82///
83///
84/// `balm::IntegerMetric` is fully *thread-safe*, meaning that all non-creator
85/// operations on a given instance can be safely invoked simultaneously from
86/// multiple threads.
87///
88/// In addition all the macros defined in this component are fully
89/// *thread-safe*, meaning that they can be safely invoked simultaneously from
90/// multiple threads.
91///
92/// ## Usage {#balm_integermetric-usage}
93///
94///
95/// This section illustrates intended use of this component.
96///
97/// ### Example 1: Metric Collection With balm::IntegerMetric {#balm_integermetric-example-1-metric-collection-with-balm-integermetric}
98///
99///
100/// We can use `balm::IntegerMetric` objects to record metric values. In this
101/// example we implement a hypothetical event manager object. We use
102/// `balm::IntegerMetric` objects to record metrics for the size of the request,
103/// the elapsed processing time, and the number of failures.
104/// @code
105/// class EventManager {
106///
107/// // DATA
108/// balm::IntegerMetric d_messageSize;
109/// balm::IntegerMetric d_elapsedTime;
110/// balm::IntegerMetric d_failedRequests;
111///
112/// public:
113///
114/// // CREATORS
115/// EventManager()
116/// : d_messageSize("MyCategory", "EventManager/size")
117/// , d_elapsedTime("MyCategory", "EventManager/elapsedTime")
118/// , d_failedRequests("MyCategory", "EventManager/failedRequests")
119/// {}
120///
121/// // MANIPULATORS
122/// int handleEvent(int eventId, const bsl::string& eventMessage)
123/// // Process the event described by the specified 'eventId' and
124/// // 'eventMessage' . Return 0 on success, and a non-zero value
125/// // if there was an error handling the event.
126/// {
127/// (void)eventId;
128///
129/// int returnCode = 0;
130///
131/// d_messageSize.update(static_cast<int>(eventMessage.size()));
132///
133/// bsls::TimeInterval start = bdlt::CurrentTime::now();
134///
135/// // Process 'data' ('returnCode' may change).
136///
137/// if (0 != returnCode) {
138/// d_failedRequests.increment();
139/// }
140///
141/// bsls::TimeInterval end = bdlt::CurrentTime::now();
142/// d_elapsedTime.update(static_cast<int>(
143/// (end - start).totalMicroseconds()));
144/// return returnCode;
145/// }
146///
147/// // ...
148/// };
149/// @endcode
150///
151/// ### Example 2: Create and Access the Default balm::MetricsManager Instance {#balm_integermetric-example-2-create-and-access-the-default-balm-metricsmanager-instance}
152///
153///
154/// This example demonstrates how to create the default `balm::MetricManager`
155/// instance and perform a trivial configuration.
156///
157/// First we create a `balm::DefaultMetricsManagerScopedGuard`, which manages
158/// the lifetime of the default metrics manager instance. At construction, we
159/// provide the scoped guard an output stream (`stdout`) that it will publish
160/// metrics to. Note that the default metrics manager is intended to be created
161/// and destroyed by the *owner* of `main`. An instance of the manager should
162/// be created during the initialization of an application (while the task has a
163/// single thread) and destroyed just prior to termination (when there is
164/// similarly a single thread).
165/// @code
166/// int main(int argc, char *argv[])
167/// {
168/// // ...
169///
170/// balm::DefaultMetricsManagerScopedGuard managerGuard(bsl::cout);
171/// @endcode
172/// Once the default instance has been created, it can be accessed using the
173/// `instance` operation.
174/// @code
175/// balm::MetricsManager *manager =
176/// balm::DefaultMetricsManager::instance();
177/// assert(0 != manager);
178/// @endcode
179/// Note that the default metrics manager will be released when `managerGuard`
180/// exits this scoped and is destroyed. Clients that choose to explicitly call
181/// `balm::DefaultMetricsManager::create` must also explicitly call
182/// `balm::DefaultMetricsManager::release()`.
183///
184/// Now that we have created a `balm::MetricsManager` instance, we can use the
185/// instance to publish metrics collected using the event manager described in
186/// {Example 1}:
187/// @code
188/// EventManager eventManager;
189///
190/// eventManager.handleEvent(0, "ab");
191/// eventManager.handleEvent(0, "abc");
192/// eventManager.handleEvent(0, "abc");
193/// eventManager.handleEvent(0, "abdef");
194///
195/// manager->publishAll();
196///
197/// eventManager.handleEvent(0, "ab");
198/// eventManager.handleEvent(0, "abc");
199/// eventManager.handleEvent(0, "abc");
200/// eventManager.handleEvent(0, "abdef");
201///
202/// eventManager.handleEvent(0, "a");
203/// eventManager.handleEvent(0, "abc");
204/// eventManager.handleEvent(0, "abc");
205/// eventManager.handleEvent(0, "abdefg");
206///
207/// manager->publishAll();
208/// }
209/// @endcode
210/// @}
211/** @} */
212/** @} */
213
214/** @addtogroup bal
215 * @{
216 */
217/** @addtogroup balm
218 * @{
219 */
220/** @addtogroup balm_integermetric
221 * @{
222 */
223
224#include <balscm_version.h>
225
229#include <balm_metricid.h>
230#include <balm_metricsmanager.h>
231#include <balm_publicationtype.h>
232
233#include <bsls_atomic.h>
234
235
236
237namespace balm {
238 // ===================
239 // class IntegerMetric
240 // ===================
241
242/// This class provides an in-core value semantic type for recording and
243/// aggregating the values of an integer metric. The value of a
244/// `IntegerMetric` object is characterized by the `IntegerCollector` object
245/// it uses to collect metric-event values. Each instance of this class
246/// establishes (at construction) an association to an `IntegerCollector`
247/// object to which the metric delegates. A `IntegerMetric` value is
248/// constant after construction (i.e., it does not support assignment or
249/// provide manipulators that modify its collector value), so that
250/// synchronization primitives are not required to protect its data members.
251///
252/// \note Note that if a collector or metrics manager is not supplied at
253/// construction, and if the default metrics manager has not been
254/// instantiated, then the metric will be inactive (i.e., `isActive()` is
255/// `false`) and the manipulator methods of the integer metric object will
256/// have no effect.
257///
258/// See @ref balm_integermetric
260
261 // DATA
262 IntegerCollector *d_collector_p; // collected metric data (held, not
263 // owned); may be 0, but cannot be
264 // invalid
265
266 const bsls::AtomicInt *d_isEnabled_p; // memo for isActive()
267
268 private:
269 // NOT IMPLEMENTED
270 IntegerMetric& operator=(const IntegerMetric& );
271
272 public:
273 // CLASS METHODS
274
275 /// Return an integer collector corresponding to the specified metric
276 /// `category` and `name`. Optionally specify a metrics `manager` used
277 /// to provide the collector. If `manager` is 0, use the default
278 /// metrics manager if initialized; if `manager` is 0 and the default
279 /// metrics manager has not been initialized, return 0.
280 ///
281 /// \pre The behavior is undefined unless `category` and `name` are null-terminated.
282 static IntegerCollector *lookupCollector(const char *category,
283 const char *name,
284 MetricsManager *manager = 0);
285
286 /// Return an integer collector for the specified `metricId`.
287 /// Optionally specify a metrics `manager` used to provide the
288 /// collector. If `manager` is 0, use the default metrics manager, if
289 /// initialized; if `manager` is 0 and the default metrics manager has not been initialized, return 0.
290 ///
291 /// \pre The behavior is undefined unless
292 /// `metricId` is a valid metric id supplied by the `MetricsRegistry`
293 /// of the indicated metrics manager.
295 MetricsManager *manager = 0);
296
297 // CREATORS
298
299 /// Create an integer metric object to collect values for the metric
300 /// identified by the specified `category` and `name`. Optionally
301 /// specify a metrics `manager` used to provide a collector for the
302 /// indicated metric. If `manager` is 0, use the default metrics
303 /// manager, if initialized; if `manager` is 0 and the default metrics
304 /// manager has not been initialized, place this metric object in the
305 /// inactive state (i.e., `isActive()` is `false`) in which case
306 /// instance methods that would otherwise update the metric will have no effect.
307 ///
308 /// \pre The behavior is undefined unless `category` and `name` are
309 /// null-terminated.
310 IntegerMetric(const char *category,
311 const char *name,
312 MetricsManager *manager = 0);
313
314 /// Create an integer metric object to collect values for the specified
315 /// `metricId`. Optionally specify a metrics `manager` used to provide
316 /// a collector for `metricId`. If `manager` is 0, use the default
317 /// metrics manager, if initialized; if `manager` is 0 and the default
318 /// metrics manager has not been initialized, place this metric object
319 /// in the inactive state (i.e., `isActive()` is `false`) in which case
320 /// instance methods that would otherwise update the metric will have no effect.
321 ///
322 /// \pre The behavior is undefined unless `metricId` is a valid
323 /// id returned by the `MetricRepository` object owned by the indicated
324 /// metrics manager.
325 explicit IntegerMetric(const MetricId& metricId,
326 MetricsManager *manager = 0);
327
328 /// Create an integer metric object to collect values for the metric
329 /// implied by the specified `collector` (i.e., `collector->metricId()`).
330 ///
331 /// \pre The behavior is undefined unless
332 /// `collector` is a valid address of a `IntegerCollector` object and
333 /// the collector object supplied has a valid id (i.e.,
334 /// `collector->metricId().isValid()`).
336
337 /// Create an integer metric object that will record values for the same
338 /// metric (i.e., using the same `IntegerCollector` object) as the
339 /// specified `original` integer metric. If the `original` metric is
340 /// inactive (i.e., `isActive() == false`), then this metric will
341 /// similarly be inactive.
342 IntegerMetric(const IntegerMetric& original);
343
344 /// Destroy this object.
345 ~IntegerMetric() = default;
346
347 // MANIPULATORS
348
349 /// Increase the count and total of this integer metric by 1; if 1 is
350 /// less than the current minimum recorded value of the metric, set the
351 /// new minimum value to be 1; if 1 is greater than the current maximum
352 /// recorded value, set the new maximum value to be 1. If, however,
353 /// this integer metric is not active (i.e., `isActive()` is `false`), then this method has no effect.
354 ///
355 /// \note Note that this method is
356 /// functionally equivalent to `update(1).`
357 void increment();
358
359 /// Increase the event count by 1 and add the specified `value` to the
360 /// total recorded value; if `value` is less than the current minimum
361 /// recorded value of the metric, set the new minimum value to be
362 /// `value`; if `value` is greater than the current maximum recorded
363 /// value, set the new maximum value to be `value`. If, however, this
364 /// integer metric is inactive (i.e., `isActive()` is `false`), then
365 /// this method has no effect.
366 void update(int value);
367
368 /// Increase the event count by the specified `count` and add the
369 /// specified `total` to the accumulated total; if the specified `min`
370 /// is less than the current minimum recorded value of the metric, set
371 /// the new minimum value to be `min`; if the specified `max` is
372 /// greater than the current maximum recorded value, set the new
373 /// maximum value to be `max`. If, however, this integer metric is
374 /// inactive (i.e., `isActive()` is `false`), then this method has no
375 /// effect.
376 void accumulateCountTotalMinMax(int count, int total, int min, int max);
377
378 /// Return the address of the modifiable integer collector for this
379 /// integer metric.
381
382 // ACCESSORS
383
384 /// Return the address of the non-modifiable integer collector for this
385 /// integer metric.
386 const IntegerCollector *collector() const;
387
388 /// Return a `MetricId` object identifying this integer metric. If
389 /// this metric was not supplied a valid integer collector at
390 /// construction then the returned id will be invalid (i.e.,
391 /// `metricId().isValid()` is `false`).
392 MetricId metricId() const;
393
394 /// Return `true` if this integer metric will actively record metrics,
395 /// and `false` otherwise. If the returned value is `false`, the
396 /// manipulator operations will have no effect. An integer metric will
397 /// be inactive if either (1) it was not initialized with a valid metric
398 /// identifier or (2) the associated metric category has been disabled
399 /// (see the `MetricsManager` method `setCategoryEnabled`).
400 ///
401 /// \note Note that invoking this method is logically equivalent to the expression
402 /// `0 != collector() && metricId().category()->enabled()`.
403 bool isActive() const;
404};
405
406// ============================================================================
407// INLINE DEFINITIONS
408// ============================================================================
409
410// FREE OPERATORS
411
412/// Return `true` if the specified `lhs` and `rhs` integer metrics have the
413/// same value and `false` otherwise. Two integer metrics have the same value
414/// if they record measurements using the same integer collector object or if
415/// they both have null collectors (i.e., `collector()` is 0).
416inline
417bool operator==(const IntegerMetric& lhs, const IntegerMetric& rhs);
418
419/// Return `true` if the specified `lhs` and `rhs` integer metrics do not have
420/// the same value and `false` otherwise. Two integer metrics do not have the
421/// same value if they record measurements using different integer collector
422/// objects or if one, but not both, have a null collector (i.e., `collector()`
423/// is 0).
424inline
425bool operator!=(const IntegerMetric& lhs, const IntegerMetric& rhs);
426
427 // ============================
428 // class IntegerMetric_MacroImp
429 // ============================
430
431/// This structure provides a namespace for functions used to implement the
432/// macros defined by this component.
433///
434/// This is an implementation type of this component and **must not** be
435/// used by clients of the `balm` package.
436///
437/// See @ref balm_integermetric
439
440 // CLASS METHODS
441
442 /// Load the specified `collector` with the address of the default
443 /// integer collector (from the default metrics manager) for the
444 /// specified `metric` identified by the specified `category` and
445 /// `name`, and register the specified `holder` for `category`.
446 ///
447 /// \note Note that `*collector` must be assigned **before** registering `holder` to
448 /// ensure that the macros always have a valid `collector` when
449 /// `holder->enabled()` is `true`.
450 static void getCollector(IntegerCollector **collector,
451 CategoryHolder *holder,
452 const char *category,
453 const char *metric);
454
455 /// Load the specified `collector` with the address of the default
456 /// integer collector (from the default metrics manager) for the
457 /// specified `metric` identified by the specified `category` and
458 /// `name`, register the specified `holder` for `category`, and set the
459 /// identified metric's preferred publication type to the specified `preferredPublicationType`.
460 ///
461 /// \note Note that `*collector` must be
462 /// assigned before `holder` to ensure that the macros always have a
463 /// valid `collector` when `holder->enabled()` is `true`.
464 static void getCollector(
465 IntegerCollector **collector,
466 CategoryHolder *holder,
467 const char *category,
468 const char *metric,
469 PublicationType::Value preferredPublicationType);
470};
471
472// ============================================================================
473// INLINE FUNCTION DEFINITIONS
474// ============================================================================
475
476 // -------------------
477 // class IntegerMetric
478 // -------------------
479
480// CLASS METHODS
481inline
483 const char *name,
484 MetricsManager *manager)
485{
486 manager = DefaultMetricsManager::manager(manager);
487 return manager
488 ? manager->
489 collectorRepository().getDefaultIntegerCollector(category, name)
490 : 0;
491}
492
493inline
495 MetricsManager *manager)
496{
497 manager = DefaultMetricsManager::manager(manager);
498 return manager
500 : 0;
501}
502
503// CREATORS
504inline
505IntegerMetric::IntegerMetric(const char *category,
506 const char *name,
507 MetricsManager *manager)
508: d_collector_p(lookupCollector(category, name, manager))
509{
510 d_isEnabled_p = (d_collector_p
511 ? &d_collector_p->metricId().category()->isEnabledRaw() : 0);
512}
513
514inline
516 MetricsManager *manager)
517: d_collector_p(lookupCollector(metricId, manager))
518{
519 d_isEnabled_p = (d_collector_p
520 ? &d_collector_p->metricId().category()->isEnabledRaw() : 0);
521}
522
523inline
525: d_collector_p(collector)
526{
527 d_isEnabled_p = &d_collector_p->metricId().category()->isEnabledRaw();
528}
529
530inline
532: d_collector_p(original.d_collector_p)
533, d_isEnabled_p(original.d_isEnabled_p)
534{
535}
536
537// MANIPULATORS
538inline
540{
541 if (this->isActive()) {
542 d_collector_p->update(1);
543 }
544}
545
546inline
548{
549 if (this->isActive()) {
550 d_collector_p->update(value);
551 }
552}
553
554inline
556 int total,
557 int min,
558 int max)
559{
560 if (this->isActive()) {
561 d_collector_p->accumulateCountTotalMinMax(count, total, min, max);
562 }
563}
564
565inline
567{
568 return d_collector_p;
569}
570
571// ACCESSORS
572inline
574{
575 return d_collector_p;
576}
577
578inline
580{
581 return d_collector_p ? d_collector_p->metricId() : MetricId();
582}
583
584inline
586{
587 return d_isEnabled_p && d_isEnabled_p->loadRelaxed();
588}
589
590} // close package namespace
591
592// FREE OPERATORS
593inline
594bool balm::operator==(const IntegerMetric& lhs, const IntegerMetric& rhs)
595{
596 return lhs.collector() == rhs.collector();
597}
598
599inline
600bool balm::operator!=(const IntegerMetric& lhs, const IntegerMetric& rhs)
601{
602 return !(lhs == rhs);
603}
604
605
606
607#endif
608
609// ----------------------------------------------------------------------------
610// Copyright 2015 Bloomberg Finance L.P.
611//
612// Licensed under the Apache License, Version 2.0 (the "License");
613// you may not use this file except in compliance with the License.
614// You may obtain a copy of the License at
615//
616// http://www.apache.org/licenses/LICENSE-2.0
617//
618// Unless required by applicable law or agreed to in writing, software
619// distributed under the License is distributed on an "AS IS" BASIS,
620// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
621// See the License for the specific language governing permissions and
622// limitations under the License.
623// ----------------------------- END-OF-FILE ----------------------------------
624
625/** @} */
626/** @} */
627/** @} */
Definition balm_category.h:263
const bsls::AtomicInt & isEnabledRaw() const
Definition balm_category.h:365
IntegerCollector * getDefaultIntegerCollector(const char *category, const char *metricName)
Definition balm_collectorrepository.h:457
Definition balm_integercollector.h:151
const MetricId & metricId() const
Definition balm_integercollector.h:322
void update(int value)
Definition balm_integercollector.h:285
void accumulateCountTotalMinMax(int count, int total, int min, int max)
Definition balm_integercollector.h:295
Definition balm_integermetric.h:259
bool isActive() const
Definition balm_integermetric.h:585
IntegerMetric(const char *category, const char *name, MetricsManager *manager=0)
Definition balm_integermetric.h:505
IntegerCollector * collector()
Definition balm_integermetric.h:566
MetricId metricId() const
Definition balm_integermetric.h:579
void increment()
Definition balm_integermetric.h:539
static IntegerCollector * lookupCollector(const char *category, const char *name, MetricsManager *manager=0)
Definition balm_integermetric.h:482
~IntegerMetric()=default
Destroy this object.
void update(int value)
Definition balm_integermetric.h:547
void accumulateCountTotalMinMax(int count, int total, int min, int max)
Definition balm_integermetric.h:555
Definition balm_metricid.h:162
const Category * category() const
Definition balm_metricid.h:330
Definition balm_metricsmanager.h:490
CollectorRepository & collectorRepository()
Definition balm_metricsmanager.h:1032
Definition bsls_atomic.h:744
int loadRelaxed() const
Definition bsls_atomic.h:1759
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition balm_bdlmmetricsadapter.h:142
bool operator==(const IntegerMetric &lhs, const IntegerMetric &rhs)
bool operator!=(const IntegerMetric &lhs, const IntegerMetric &rhs)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
static MetricsManager * manager(MetricsManager *manager=0)
Definition balm_defaultmetricsmanager.h:316
Definition balm_integermetric.h:438
static void getCollector(IntegerCollector **collector, CategoryHolder *holder, const char *category, const char *metric, PublicationType::Value preferredPublicationType)
static void getCollector(IntegerCollector **collector, CategoryHolder *holder, const char *category, const char *metric)
Value
Definition balm_publicationtype.h:83