BDE 4.14.0 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/// Note that if a collector or metrics manager is not supplied at
252/// construction, and if the default metrics manager has not been
253/// instantiated, then the metric will be inactive (i.e., `isActive()` is
254/// `false`) and the manipulator methods of the integer metric object will
255/// have no effect.
256///
257/// See @ref balm_integermetric
259
260 // DATA
261 IntegerCollector *d_collector_p; // collected metric data (held, not
262 // owned); may be 0, but cannot be
263 // invalid
264
265 const bsls::AtomicInt *d_isEnabled_p; // memo for isActive()
266
267 // NOT IMPLEMENTED
268 IntegerMetric& operator=(const IntegerMetric& );
269
270 public:
271 // CLASS METHODS
272
273 /// Return an integer collector corresponding to the specified metric
274 /// `category` and `name`. Optionally specify a metrics `manager` used
275 /// to provide the collector. If `manager` is 0, use the default
276 /// metrics manager if initialized; if `manager` is 0 and the default
277 /// metrics manager has not been initialized, return 0. The behavior
278 /// is undefined unless `category` and `name` are null-terminated.
279 static IntegerCollector *lookupCollector(const char *category,
280 const char *name,
281 MetricsManager *manager = 0);
282
283 /// Return an integer collector for the specified `metricId`.
284 /// Optionally specify a metrics `manager` used to provide the
285 /// collector. If `manager` is 0, use the default metrics manager, if
286 /// initialized; if `manager` is 0 and the default metrics manager has
287 /// not been initialized, return 0. The behavior is undefined unless
288 /// `metricId` is a valid metric id supplied by the `MetricsRegistry`
289 /// of the indicated metrics manager.
291 MetricsManager *manager = 0);
292
293 // CREATORS
294
295 /// Create an integer metric object to collect values for the metric
296 /// identified by the specified `category` and `name`. Optionally
297 /// specify a metrics `manager` used to provide a collector for the
298 /// indicated metric. If `manager` is 0, use the default metrics
299 /// manager, if initialized; if `manager` is 0 and the default metrics
300 /// manager has not been initialized, place this metric object in the
301 /// inactive state (i.e., `isActive()` is `false`) in which case
302 /// instance methods that would otherwise update the metric will have no
303 /// effect. The behavior is undefined unless `category` and `name` are
304 /// null-terminated.
305 IntegerMetric(const char *category,
306 const char *name,
307 MetricsManager *manager = 0);
308
309 /// Create an integer metric object to collect values for the specified
310 /// `metricId`. Optionally specify a metrics `manager` used to provide
311 /// a collector for `metricId`. If `manager` is 0, use the default
312 /// metrics manager, if initialized; if `manager` is 0 and the default
313 /// metrics manager has not been initialized, place this metric object
314 /// in the inactive state (i.e., `isActive()` is `false`) in which case
315 /// instance methods that would otherwise update the metric will have
316 /// no effect. The behavior is undefined unless `metricId` is a valid
317 /// id returned by the `MetricRepository` object owned by the indicated
318 /// metrics manager.
319 explicit IntegerMetric(const MetricId& metricId,
320 MetricsManager *manager = 0);
321
322 /// Create an integer metric object to collect values for the metric
323 /// implied by the specified `collector` (i.e.,
324 /// `collector->metricId()`). The behavior is undefined unless
325 /// `collector` is a valid address of a `IntegerCollector` object and
326 /// the collector object supplied has a valid id (i.e.,
327 /// `collector->metricId().isValid()`).
329
330 /// Create an integer metric object that will record values for the same
331 /// metric (i.e., using the same `IntegerCollector` object) as the
332 /// specified `original` integer metric. If the `original` metric is
333 /// inactive (i.e., `isActive() == false`), then this metric will
334 /// similarly be inactive.
335 IntegerMetric(const IntegerMetric& original);
336
337 /// Destroy this object.
338 ~IntegerMetric() = default;
339
340 // MANIPULATORS
341
342 /// Increase the count and total of this integer metric by 1; if 1 is
343 /// less than the current minimum recorded value of the metric, set the
344 /// new minimum value to be 1; if 1 is greater than the current maximum
345 /// recorded value, set the new maximum value to be 1. If, however,
346 /// this integer metric is not active (i.e., `isActive()` is `false`),
347 /// then this method has no effect. Note that this method is
348 /// functionally equivalent to `update(1).`
349 void increment();
350
351 /// Increase the event count by 1 and add the specified `value` to the
352 /// total recorded value; if `value` is less than the current minimum
353 /// recorded value of the metric, set the new minimum value to be
354 /// `value`; if `value` is greater than the current maximum recorded
355 /// value, set the new maximum value to be `value`. If, however, this
356 /// integer metric is inactive (i.e., `isActive()` is `false`), then
357 /// this method has no effect.
358 void update(int value);
359
360 /// Increase the event count by the specified `count` and add the
361 /// specified `total` to the accumulated total; if the specified `min`
362 /// is less than the current minimum recorded value of the metric, set
363 /// the new minimum value to be `min`; if the specified `max` is
364 /// greater than the current maximum recorded value, set the new
365 /// maximum value to be `max`. If, however, this integer metric is
366 /// inactive (i.e., `isActive()` is `false`), then this method has no
367 /// effect.
368 void accumulateCountTotalMinMax(int count, int total, int min, int max);
369
370 /// Return the address of the modifiable integer collector for this
371 /// integer metric.
373
374 // ACCESSORS
375
376 /// Return the address of the non-modifiable integer collector for this
377 /// integer metric.
378 const IntegerCollector *collector() const;
379
380 /// Return a `MetricId` object identifying this integer metric. If
381 /// this metric was not supplied a valid integer collector at
382 /// construction then the returned id will be invalid (i.e.,
383 /// `metricId().isValid()` is `false`).
384 MetricId metricId() const;
385
386 /// Return `true` if this integer metric will actively record metrics,
387 /// and `false` otherwise. If the returned value is `false`, the
388 /// manipulator operations will have no effect. An integer metric will
389 /// be inactive if either (1) it was not initialized with a valid metric
390 /// identifier or (2) the associated metric category has been disabled
391 /// (see the `MetricsManager` method `setCategoryEnabled`). Note that
392 /// invoking this method is logically equivalent to the expression
393 /// `0 != collector() && metricId().category()->enabled()`.
394 bool isActive() const;
395};
396
397// ============================================================================
398// INLINE DEFINITIONS
399// ============================================================================
400
401// FREE OPERATORS
402
403/// Return `true` if the specified `lhs` and `rhs` integer metrics have the
404/// same value and `false` otherwise. Two integer metrics have the same value
405/// if they record measurements using the same integer collector object or if
406/// they both have null collectors (i.e., `collector()` is 0).
407inline
408bool operator==(const IntegerMetric& lhs, const IntegerMetric& rhs);
409
410/// Return `true` if the specified `lhs` and `rhs` integer metrics do not have
411/// the same value and `false` otherwise. Two integer metrics do not have the
412/// same value if they record measurements using different integer collector
413/// objects or if one, but not both, have a null collector (i.e., `collector()`
414/// is 0).
415inline
416bool operator!=(const IntegerMetric& lhs, const IntegerMetric& rhs);
417
418 // ============================
419 // class IntegerMetric_MacroImp
420 // ============================
421
422/// This structure provides a namespace for functions used to implement the
423/// macros defined by this component.
424///
425/// This is an implementation type of this component and **must not** be
426/// used by clients of the `balm` package.
428
429 // CLASS METHODS
430
431 /// Load the specified `collector` with the address of the default
432 /// integer collector (from the default metrics manager) for the
433 /// specified `metric` identified by the specified `category` and
434 /// `name`, and register the specified `holder` for `category`. Note
435 /// that `*collector` must be assigned **before** registering `holder` to
436 /// ensure that the macros always have a valid `collector` when
437 /// `holder->enabled()` is `true`.
438 static void getCollector(IntegerCollector **collector,
439 CategoryHolder *holder,
440 const char *category,
441 const char *metric);
442
443 /// Load the specified `collector` with the address of the default
444 /// integer collector (from the default metrics manager) for the
445 /// specified `metric` identified by the specified `category` and
446 /// `name`, register the specified `holder` for `category`, and set the
447 /// identified metric's preferred publication type to the specified
448 /// `preferredPublicationType`. Note that `*collector` must be
449 /// assigned before `holder` to ensure that the macros always have a
450 /// valid `collector` when `holder->enabled()` is `true`.
451 static void getCollector(
452 IntegerCollector **collector,
453 CategoryHolder *holder,
454 const char *category,
455 const char *metric,
456 PublicationType::Value preferredPublicationType);
457};
458
459// ============================================================================
460// INLINE FUNCTION DEFINITIONS
461// ============================================================================
462
463 // -------------------
464 // class IntegerMetric
465 // -------------------
466
467// CLASS METHODS
468inline
470 const char *name,
471 MetricsManager *manager)
472{
473 manager = DefaultMetricsManager::manager(manager);
474 return manager
475 ? manager->
476 collectorRepository().getDefaultIntegerCollector(category, name)
477 : 0;
478}
479
480inline
482 MetricsManager *manager)
483{
484 manager = DefaultMetricsManager::manager(manager);
485 return manager
487 : 0;
488}
489
490// CREATORS
491inline
492IntegerMetric::IntegerMetric(const char *category,
493 const char *name,
494 MetricsManager *manager)
495: d_collector_p(lookupCollector(category, name, manager))
496{
497 d_isEnabled_p = (d_collector_p
498 ? &d_collector_p->metricId().category()->isEnabledRaw() : 0);
499}
500
501inline
503 MetricsManager *manager)
504: d_collector_p(lookupCollector(metricId, manager))
505{
506 d_isEnabled_p = (d_collector_p
507 ? &d_collector_p->metricId().category()->isEnabledRaw() : 0);
508}
509
510inline
512: d_collector_p(collector)
513{
514 d_isEnabled_p = &d_collector_p->metricId().category()->isEnabledRaw();
515}
516
517inline
519: d_collector_p(original.d_collector_p)
520, d_isEnabled_p(original.d_isEnabled_p)
521{
522}
523
524// MANIPULATORS
525inline
527{
528 if (this->isActive()) {
529 d_collector_p->update(1);
530 }
531}
532
533inline
535{
536 if (this->isActive()) {
537 d_collector_p->update(value);
538 }
539}
540
541inline
543 int total,
544 int min,
545 int max)
546{
547 if (this->isActive()) {
548 d_collector_p->accumulateCountTotalMinMax(count, total, min, max);
549 }
550}
551
552inline
554{
555 return d_collector_p;
556}
557
558// ACCESSORS
559inline
561{
562 return d_collector_p;
563}
564
565inline
567{
568 return d_collector_p ? d_collector_p->metricId() : MetricId();
569}
570
571inline
573{
574 return d_isEnabled_p && d_isEnabled_p->loadRelaxed();
575}
576
577} // close package namespace
578
579// FREE OPERATORS
580inline
581bool balm::operator==(const IntegerMetric& lhs, const IntegerMetric& rhs)
582{
583 return lhs.collector() == rhs.collector();
584}
585
586inline
587bool balm::operator!=(const IntegerMetric& lhs, const IntegerMetric& rhs)
588{
589 return !(lhs == rhs);
590}
591
592
593
594#endif
595
596// ----------------------------------------------------------------------------
597// Copyright 2015 Bloomberg Finance L.P.
598//
599// Licensed under the Apache License, Version 2.0 (the "License");
600// you may not use this file except in compliance with the License.
601// You may obtain a copy of the License at
602//
603// http://www.apache.org/licenses/LICENSE-2.0
604//
605// Unless required by applicable law or agreed to in writing, software
606// distributed under the License is distributed on an "AS IS" BASIS,
607// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
608// See the License for the specific language governing permissions and
609// limitations under the License.
610// ----------------------------- END-OF-FILE ----------------------------------
611
612/** @} */
613/** @} */
614/** @} */
Definition balm_category.h:257
const bsls::AtomicInt & isEnabledRaw() const
Definition balm_category.h:346
IntegerCollector * getDefaultIntegerCollector(const char *category, const char *metricName)
Definition balm_collectorrepository.h:444
Definition balm_integercollector.h:151
const MetricId & metricId() const
Definition balm_integercollector.h:319
void update(int value)
Definition balm_integercollector.h:282
void accumulateCountTotalMinMax(int count, int total, int min, int max)
Definition balm_integercollector.h:292
Definition balm_integermetric.h:258
bool isActive() const
Definition balm_integermetric.h:572
IntegerMetric(const char *category, const char *name, MetricsManager *manager=0)
Definition balm_integermetric.h:492
IntegerCollector * collector()
Definition balm_integermetric.h:553
MetricId metricId() const
Definition balm_integermetric.h:566
void increment()
Definition balm_integermetric.h:526
static IntegerCollector * lookupCollector(const char *category, const char *name, MetricsManager *manager=0)
Definition balm_integermetric.h:469
~IntegerMetric()=default
Destroy this object.
void update(int value)
Definition balm_integermetric.h:534
void accumulateCountTotalMinMax(int count, int total, int min, int max)
Definition balm_integermetric.h:542
Definition balm_metricid.h:162
const Category * category() const
Definition balm_metricid.h:319
Definition balm_metricsmanager.h:490
CollectorRepository & collectorRepository()
Definition balm_metricsmanager.h:1013
Definition bsls_atomic.h:743
int loadRelaxed() const
Definition bsls_atomic.h:1738
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balm_bdlmmetricsadapter.h:141
bool operator==(const IntegerMetric &lhs, const IntegerMetric &rhs)
bool operator!=(const IntegerMetric &lhs, const IntegerMetric &rhs)
static MetricsManager * manager(MetricsManager *manager=0)
Definition balm_defaultmetricsmanager.h:302
Definition balm_integermetric.h:427
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:81