BDE 4.14.0 Production release
Loading...
Searching...
No Matches
balm_metricsmanager.h
Go to the documentation of this file.
1/// @file balm_metricsmanager.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balm_metricsmanager.h -*-C++-*-
8#ifndef INCLUDED_BALM_METRICSMANAGER
9#define INCLUDED_BALM_METRICSMANAGER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balm_metricsmanager balm_metricsmanager
15/// @brief Provide a manager for recording and publishing metric data.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balm
19/// @{
20/// @addtogroup balm_metricsmanager
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balm_metricsmanager-purpose"> Purpose</a>
25/// * <a href="#balm_metricsmanager-classes"> Classes </a>
26/// * <a href="#balm_metricsmanager-description"> Description </a>
27/// * <a href="#balm_metricsmanager-alternative-systems-for-telemetry"> Alternative Systems for Telemetry </a>
28/// * <a href="#balm_metricsmanager-thread-safety"> Thread Safety </a>
29/// * <a href="#balm_metricsmanager-registered-concrete-balm-publisher-implementations"> Registered Concrete balm::Publisher Implementations </a>
30/// * <a href="#balm_metricsmanager-registered-recordscollectioncallback-implementations"> Registered RecordsCollectionCallback Implementations </a>
31/// * <a href="#balm_metricsmanager-usage"> Usage </a>
32/// * <a href="#balm_metricsmanager-example-1-initialize-a-balm-metricsmanager"> Example 1: Initialize a balm::MetricsManager </a>
33/// * <a href="#balm_metricsmanager-example-2-recording-metric-values-with-balm-collector"> Example 2: Recording Metric Values with balm::Collector </a>
34/// * <a href="#balm_metricsmanager-example-3-recording-metric-values-with-a-callback"> Example 3: Recording Metric Values with a Callback </a>
35/// * <a href="#balm_metricsmanager-example-4-publishing-a-metric"> Example 4: Publishing a Metric </a>
36///
37/// # Purpose {#balm_metricsmanager-purpose}
38/// Provide a manager for recording and publishing metric data.
39///
40/// # Classes {#balm_metricsmanager-classes}
41///
42/// - balm::MetricsManager: manager for recording and publishing metric data
43///
44/// @see balm_publisher, balm_collectorrepository, balm_metricregistry,
45/// balm_metric, balm_defaultmetricsmanager, balm_publicationscheduler
46///
47/// # Description {#balm_metricsmanager-description}
48/// This component provides a `balm::MetricsManager` class for
49/// managing the recording and publishing of metric data. The metrics manager
50/// retrieves `balm::MetricRecords` from both the collector repository it owns
51/// as well as any `RecordsCollectionCallbacks` registered with it. The metrics
52/// manager also provides methods to register `balm::Publisher` objects. The
53/// `publish` method collects metrics for a category (or set of categories) and
54/// then sends the collected metrics to the publishers associated with that
55/// category (or set of categories).
56///
57/// Note that a metric in this context is an event associated with a measured
58/// value. This component does *not* define what constitutes an event or what
59/// the associated value represents. A collected metric contains the count of
60/// event occurrences along with the total, minimum, and maximum aggregates of
61/// the measured values.
62///
63/// ## Alternative Systems for Telemetry {#balm_metricsmanager-alternative-systems-for-telemetry}
64///
65///
66/// Bloomberg software may alternatively use the GUTS telemetry API, which is
67/// integrated into Bloomberg infrastructure.
68///
69/// ## Thread Safety {#balm_metricsmanager-thread-safety}
70///
71///
72/// `balm::MetricsManager` is fully *thread-safe*, meaning that all non-creator
73/// operations on a given instance can be safely invoked simultaneously from
74/// multiple threads. To avoid synchronization problems with user functions
75/// invoked by `balm::MetricsManager`, special consideration must be taken when
76/// implementing these functions as specified below.
77///
78/// ### Registered Concrete balm::Publisher Implementations {#balm_metricsmanager-registered-concrete-balm-publisher-implementations}
79///
80///
81/// Concrete implementations of the `balm::Publisher` protocol (pure abstract
82/// base-class) registered with a `balm::MetricsManager` object must *not* call
83/// (either directly or indirectly) the `publish` method on the
84/// `balm::MetricsManager` object with which they are registered.
85///
86/// ### Registered RecordsCollectionCallback Implementations {#balm_metricsmanager-registered-recordscollectioncallback-implementations}
87///
88///
89/// Implementations of `balm::MetricsManager::RecordsCollectionCallback`
90/// registered with a `balm::MetricsManager` will be invoked by a function
91/// holding mutex locks that provide synchronized access to data in that
92/// `balm::MetricsManager`. Therefore registered implementations of
93/// `RecordsCollectionCallback` must *not* make any re-entrant calls (either
94/// directly or indirectly) to member functions of the `balm::MetricManager`
95/// object with which they are registered.
96///
97/// ## Usage {#balm_metricsmanager-usage}
98///
99///
100/// This section illustrates intended use of this component.
101///
102/// ### Example 1: Initialize a balm::MetricsManager {#balm_metricsmanager-example-1-initialize-a-balm-metricsmanager}
103///
104///
105/// This example demonstrates how to create and configure a
106/// `balm::MetricsManager` that we will use to record and publish metric values.
107/// We first create a `balm::MetricsManager` object and a
108/// `SimpleStreamPublisher` object. Note that `SimpleStreamPublisher` is an
109/// example implementation of the `balm::Publisher` protocol defined in the
110/// @ref balm_publisher component. In practice, clients typically use a standard
111/// publisher class (e.g., `balm::StreamPublisher`).
112/// @code
113/// int main(int argc, char *argv[]) {
114/// {
115///
116/// // ...
117///
118/// bslma::Allocator *allocator = bslma::Default::allocator(0);
119/// balm::MetricsManager manager(allocator);
120///
121/// bsl::shared_ptr<balm::Publisher> publisher(
122/// new (*allocator) SimpleStreamPublisher(bsl::cout),
123/// allocator);
124/// manager.addGeneralPublisher(publisher);
125///
126/// // ...
127///
128/// @endcode
129///
130/// ### Example 2: Recording Metric Values with balm::Collector {#balm_metricsmanager-example-2-recording-metric-values-with-balm-collector}
131///
132///
133/// This second example demonstrates using `balm::Collector` objects (obtained
134/// from a metrics manager's collector repository) to collect metrics related to
135/// a hypothetical `EventHandler` class. On construction, the event handler
136/// obtains references to `balm::Collector` objects from the metrics manager's
137/// collector repository. On each handled event, the `EventHandler`, updates
138/// its collectors with the appropriate metric values.
139///
140/// Note that the @ref balm_metric component provides both classes and macros to
141/// reduce the code required for collecting metric values.
142/// @code
143/// class EventHandler {
144/// // Provide an example event-handling mechanism that records metrics
145/// // for (1) the size of the processed event messages and (2) the number
146/// // of failures, using 'balm::Collector' objects provided by a
147/// // 'balm::MetricsManager'.
148///
149/// // PRIVATE DATA
150/// balm::Collector *d_eventMessageSizes_p; // collect the message sizes
151///
152/// balm::Collector *d_eventFailures_p; // collect the number of
153/// // failures
154///
155/// // ...
156///
157/// public:
158/// // CREATORS
159/// @endcode
160/// We obtain the addresses of the respective `balm::Collector` objects that we
161/// will use to collect metrics values from the metrics managers' collector
162/// repository. Note that, in practice, clients can use the
163/// `balm::DefaultMetricManager` (see @ref balm_defaultmetricsmanager and
164/// @ref balm_metric ) rather than explicitly pass the address of a metrics manager.
165/// @code
166/// EventHandler(balm::MetricsManager *manager)
167/// : d_eventMessageSizes_p(
168/// manager->collectorRepository().getDefaultCollector(
169/// "MyCategory", "messageSizes"))
170/// , d_eventFailures_p(
171/// manager->collectorRepository().getDefaultCollector(
172/// "MyCategory", "eventFailures"))
173/// {}
174///
175/// // MANIPULATORS
176/// @endcode
177/// Then, when processing an "event", we update the `balm::Collector` objects
178/// with the appropriate metric values for the event.
179/// @code
180/// int handleEvent(int eventId, const bsl::string& eventMessage)
181/// // Process the event described by the specified 'eventId' and
182/// // 'eventMessage' . Return 0 on success, and a non-zero value
183/// // if there was an error handling the event.
184/// {
185/// int returnCode = 0;
186/// d_eventMessageSizes_p->update(
187/// static_cast<double>(eventMessage.size()));
188///
189/// // ... (Process the event)
190/// (void)eventId;
191///
192/// if (0 != returnCode) {
193/// d_eventFailures_p->update(1);
194/// }
195/// return returnCode;
196/// }
197///
198/// // ...
199///
200/// };
201/// @endcode
202///
203/// ### Example 3: Recording Metric Values with a Callback {#balm_metricsmanager-example-3-recording-metric-values-with-a-callback}
204///
205///
206/// The metrics manager provides a facility to register a callback that will
207/// report metric values. A callback should be used if clients want to
208/// customize how a metric, or group of metrics, are recorded. In the following
209/// example, the `EventHandlerWithCallback` class maintains a metric for the
210/// average number of events per second that it reports through a
211/// `balm::MetricsManager::MetricsCollectionCallback`.
212/// @code
213/// // eventhandlerwithcallback.h
214///
215/// class EventHandlerWithCallback {
216/// // Provide an example event handling mechanism that records a
217/// // metric for the number of events per second and reports that metric
218/// // using a 'balm::MetricsManager::RecordsCollectionCallback'.
219///
220/// // PRIVATE DATA
221/// bsls::AtomicInt d_numEvents; // number of events
222///
223/// bsls::TimeInterval d_periodStart; // start of the current
224/// // period
225///
226/// balm::MetricId d_eventsPerSecId; // identifies the events-
227/// // per-second metric
228/// balm::MetricsManager::CallbackHandle
229/// d_callbackHandle; // identifies the callback
230///
231/// balm::MetricsManager *d_metricsManager_p; // metrics manager (held,
232/// // but not owned)
233/// // ...
234///
235/// // PRIVATE MANIPULATORS
236/// void collectMetricsCb(bsl::vector<balm::MetricRecord> *records,
237/// bool resetFlag);
238/// // Append to the specified 'records' the aggregated values of the
239/// // metrics recorded by this event handler and, if 'resetFlag' is
240/// // 'true', reset those metric values to their default state. Note
241/// // that this method is intended to be used as a callback, and is
242/// // consistent with the
243/// // 'balm::MetricsManager::RecordsCollectionCallback' function
244/// // prototype.
245///
246/// public:
247/// // CREATORS
248/// EventHandlerWithCallback(balm::MetricsManager *manager,
249/// bslma::Allocator *basicAllocator = 0);
250/// // Initialize this object to use the specified 'manager' to record
251/// // and publish metrics. Optionally specify a 'basicAllocator'
252/// // used to supply memory. If 'basicAllocator' is 0, the currently
253/// // installed default allocator is used.
254///
255/// ~EventHandlerWithCallback();
256/// // Destroy this event handler.
257///
258/// // MANIPULATORS
259/// int handleEvent(int eventId, const bsl::string& eventMessage);
260/// // Process the event described by the specified 'eventId' and
261/// // 'eventMessage'. Return 0 on success, and a non-zero value if
262/// // there was an error processing the event.
263///
264/// // ...
265///
266/// };
267/// @endcode
268/// In the implementation of `EventHandlerWithCallback` below, we ensure that
269/// the callback is registered on construction and removed before the object is
270/// destroyed.
271/// @code
272/// // eventhandlerwithcallback.cpp
273///
274/// namespace {
275///
276/// const char *METRIC_CATEGORY = "MyCategory";
277///
278/// }
279///
280/// @endcode
281/// The callback creates metric records and populates them with data collected
282/// by the event handler.
283/// @code
284/// // PRIVATE MANIPULATORS
285/// void EventHandlerWithCallback::collectMetricsCb(
286/// bsl::vector<balm::MetricRecord> *records,
287/// bool resetFlag)
288/// {
289/// int numEvents = resetFlag ?
290/// (int)d_numEvents.swap(0) :
291/// (int)d_numEvents;
292/// bsls::TimeInterval now = bdlt::CurrentTime::now();
293/// bsls::TimeInterval elapsedTime = now - d_periodStart;
294/// d_periodStart = now;
295///
296/// balm::MetricRecord record(d_eventsPerSecId);
297/// record.count() = 1;
298/// record.total() = numEvents / elapsedTime.totalSecondsAsDouble();
299///
300/// records->push_back(record);
301/// }
302///
303/// @endcode
304/// In the constructor, we initialize a metric id from the specified `manager`
305/// object's metric registry. We will also register the collection callback
306/// (`collectMetricsCb`) with the supplied `manager`.
307/// @code
308/// // CREATORS
309/// EventHandlerWithCallback::EventHandlerWithCallback(
310/// balm::MetricsManager *manager,
311/// bslma::Allocator *basicAllocator)
312/// : d_numEvents(0)
313/// , d_periodStart(bdlt::CurrentTime::now())
314/// , d_eventsPerSecId()
315/// , d_callbackHandle(balm::MetricsManager::e_INVALID_HANDLE)
316/// , d_metricsManager_p(manager)
317/// {
318/// (void)basicAllocator;
319///
320/// d_eventsPerSecId = d_metricsManager_p->metricRegistry().getId(
321/// METRIC_CATEGORY, "eventsPerSecond");
322/// @endcode
323/// We now register the callback function `collectMetricsCb` with the metrics
324/// manager. We use `bdlf::BindUtil` to bind the member function to a
325/// `bsl::function` matching the
326/// `balm::MetricsManager::RecordsCollectionCallback` function prototype. The
327/// private data member `d_callbackHandle` is used to store the
328/// `balm::MetricsManager::CallbackHandle` returned for the registered callback;
329/// we will use this handle later to remove the callback from the metrics
330/// manager.
331/// @code
332/// d_callbackHandle =
333/// d_metricsManager_p->registerCollectionCallback(
334/// METRIC_CATEGORY,
335/// bdlf::BindUtil::bindA(basicAllocator,
336/// &EventHandlerWithCallback::collectMetricsCb,
337/// this,
338/// bdlf::PlaceHolders::_1,
339/// bdlf::PlaceHolders::_2));
340/// }
341///
342/// @endcode
343/// In the destructor we use the `balm::MetricsManager::CallbackHandle`, stored
344/// in `d_callbackHandle`, to remove the callback from the metrics manager.
345/// This prevents the metrics manager from invoking the callback method on an
346/// object that has already been destroyed.
347/// @code
348/// EventHandlerWithCallback::~EventHandlerWithCallback()
349/// {
350/// int rc =
351/// d_metricsManager_p->removeCollectionCallback(d_callbackHandle);
352/// assert(0 == rc);
353/// }
354///
355/// // MANIPULATORS
356/// int EventHandlerWithCallback::handleEvent(int eventId,
357/// const bsl::string& eventMessage)
358/// {
359/// @endcode
360/// We increment the atomic integer `d_numEvents` to keep track of the number
361/// events handled by the `handleEvent` method. If collecting a metric is
362/// expensive (e.g., metrics requiring a system call to collect), clients should
363/// test whether the metric is enabled before performing the collection
364/// operation.
365/// @code
366/// // We don't test 'd_eventsPerSecId.category()->enabled())' before
367/// // incrementing 'd_numEvents' because, in this instance, it will not
368/// // improve performance.
369/// ++d_numEvents;
370///
371/// // ... (Process the event)
372/// (void)eventId;
373/// (void)eventMessage;
374///
375/// return 0;
376/// }
377///
378/// // ...
379/// @endcode
380///
381/// ### Example 4: Publishing a Metric {#balm_metricsmanager-example-4-publishing-a-metric}
382///
383///
384/// The metrics manager provides a `publish` operation to publish metrics for a
385/// category or set of categories. In this example we will use the metrics
386/// manager's `publishAll` operation to publish all the metrics managed by the
387/// metrics manager. We will record metrics for "MyCategory" using instances of
388/// the `EventHandler` and `EventHandlerWithCallback` classes (defined above).
389/// This example assumes that an instance, `manager`, of the
390/// `balm::MetricsManager` class has been initialized as in example 1. Note
391/// that, in practice the publish operation is normally tied to a scheduling
392/// mechanism (e.g., see @ref balm_publicationscheduler ).
393/// @code
394/// EventHandler eventHandler(&manager);
395/// EventHandlerWithCallback eventHandlerWithCallback(&manager);
396///
397/// eventHandler.handleEvent(0, "A 28 character event message");
398/// eventHandlerWithCallback.handleEvent(1, "A different event message");
399/// manager.publishAll();
400///
401/// eventHandler.handleEvent(0, "A 28 character event message");
402/// eventHandler.handleEvent(0, "A 28 character event message");
403/// eventHandlerWithCallback.handleEvent(1, "A different event message");
404/// manager.publishAll();
405/// @endcode
406/// Executing the example should result in two samples being published to
407/// standard output. Each sample should contain 3 metrics belonging to the
408/// metric category "MyCategory". The metric "eventsPerSecond" is collected by
409/// the `EventHandlerWithCallback`, while "messageSizes", and "eventFailures"
410/// (both collected by `EventHandler`).
411/// @code
412/// 09FEB2009_18:52:51.093+0000 3 Records
413/// Elapsed Time: 0.001358s
414/// MyCategory.eventsPerSecond [count = 1, total = 2267.57, ... ]
415/// MyCategory.messageSizes [count = 1, total = 28, min = 28, max = 28]
416/// MyCategory.eventFailures [count = 0, total = 0, ... ]
417/// 09FEB2009_18:52:51.096+0000 3 Records
418/// Elapsed Time: 0.002217s
419/// MyCategory.eventsPerSecond [count = 1, total = 453.721, ... ]
420/// MyCategory.messageSizes [count = 2, total = 56, min = 28, max = 28]
421/// MyCategory.eventFailures [count = 0, total = 0, ... ]
422/// @endcode
423/// @}
424/** @} */
425/** @} */
426
427/** @addtogroup bal
428 * @{
429 */
430/** @addtogroup balm
431 * @{
432 */
433/** @addtogroup balm_metricsmanager
434 * @{
435 */
436
437#include <balscm_version.h>
438
440#include <balm_metricregistry.h>
441
442#include <bslmt_rwmutex.h>
443
444#include <bsls_timeinterval.h>
445
446#include <bslma_allocator.h>
447#include <bslma_managedptr.h>
448
450
451#include <bsls_libraryfeatures.h>
452
453#include <bsl_functional.h>
454#include <bsl_map.h>
455#include <bsl_memory.h>
456#include <bsl_set.h>
457#include <bsl_vector.h>
458
459#include <set> // 'std::set', 'std::pmr::set'
460#include <vector> // 'std::vector', 'std::pmr::vector'
461
462
463
464namespace balm {
465
466class Category;
467class Publisher;
468class MetricRecord;
469class MetricSample;
470
471class MetricsManager_PublisherRegistry; // defined in implementation
472class MetricsManager_CallbackRegistry; // defined in implementation
473struct MetricsManager_PublicationHelper; // defined in implementation
474
475 // ====================
476 // class MetricsManager
477 // ====================
478
479/// This class implements a manager for the recording and publishing of
480/// metrics. Metrics managed by a `MetricsManager` are grouped into
481/// categories identified by a string. The metrics manager allows clients
482/// to register a `Publisher` object using the `addGeneralPublisher` and
483/// `addSpecificPublisher` operations. Metrics can be recorded in one of
484/// two ways: Clients can (1) implement their own metric collection
485/// facilities and register a callback using this metric manager's
486/// `registerMetricsCallback` method; or (2) use the `Collector` objects
487/// available from the `CollectorRepository` owned by this metrics manager.
488///
489/// See @ref balm_metricsmanager
491
492 public:
493 // TYPES
494
495 /// `RecordsCollectionCallback` is an alias for a callback function
496 /// that appends to the supplied `MetricRecord` vector the values of the
497 /// collected metrics, and, if the provided `bool` is `true`, resets
498 /// those metrics to their default values. Clients can register
499 /// callbacks matching this prototype with the metrics manager. Here is
500 /// an example prototype matching this callback:
501 /// @code
502 /// void collectionCb(bsl::vector<MetricRecord> *records,
503 /// bool resetFlag);
504 /// @endcode
505 typedef bsl::function<void(bsl::vector<MetricRecord> *, bool)>
507
508 /// Identifies a registered `RecordsCollectionCallback`.
509 typedef int CallbackHandle;
510
511 private:
512 // PRIVATE TYPES
513
514 /// A mapping from a category to the most recent reset (represented as
515 /// the interval since the epoch) of that category. This is used to
516 /// compute the time interval over which a metric was collected.
518
519 // DATA
520 MetricRegistry d_metricRegistry; // registry of metrics
521
522 CollectorRepository d_collectors; // repository of metric
523 // collectors
524
526 d_callbacks; // registry of callbacks
527 // (owned)
528
530 d_publishers; // registry of publishers
531 // (owned)
532
533 bsls::TimeInterval d_creationTime; // time this object was
534 // created
535
536 LastResetTimes d_prevResetTimes; // time of a category's
537 // previous reset
538
539 bslmt::Mutex d_publishLock; // lock for 'publish',
540 // acquired before 'd_rwLock'
541
542 mutable bslmt::RWMutex d_rwLock; // lock for the data maps
543
544 bslma::Allocator *d_allocator_p; // allocator (held not owned)
545
546 // FRIENDS
548
549 private:
550 // NOT IMPLEMENTED
552 MetricsManager& operator=(const MetricsManager& );
553
554 public:
555 // CONSTANTS
556 enum {
557 e_INVALID_HANDLE = -1 // an invalid callback handle
558#ifndef BDE_OMIT_INTERNAL_DEPRECATED
560#endif // BDE_OMIT_INTERNAL_DEPRECATED
561 };
562
563 // TRAITS
565
566 private:
567 // PRIVATE MANIPULATORS
568
569 /// Load into the specified `sample` a metric sample collected from the
570 /// indicated categories, and append to `records` those collected
571 /// records which are referred to by `sample`. Optionally specify a
572 /// `resetFlag` that determines if the collected metrics are reset as
573 /// part of this operation. This operation will collect aggregated
574 /// metric values for each *enabled* category in the specified
575 /// categories from registered callbacks as well as from its own
576 /// `CollectorRepository`, and then append those values to `records` and
577 /// update `sample` with the addresses of those collected `records`. If
578 /// `resetFlag` is `true`, the metrics being collected are reset to
579 /// their default state. This operation also populates the `sample`
580 /// with the time interval is computed as the elapsed time since the
581 /// interval over which the sampled metrics were collected. This last
582 /// time the metrics were reset (either through a call to the `publish`
583 /// or `collectSample` methods). If `category` has not previously been
584 /// reset then this interval is taken to be the elapsed time since the
585 /// creation of this metrics manager. The behavior is undefined unless
586 /// `0 <= numCategories`, `categories` refers to a contiguous sequence
587 /// of (at least) `numCategories`, and each category in `categories`
588 /// appears only once. Note that `sample` is loaded with the
589 /// *addresses* of the metric records appended to `records`, and
590 /// modifying `records` after this call returns may invalidate `sample`.
591 void collectSampleImp(MetricSample *sample,
593 const Category * const categories[],
594 int numCategories,
595 bool resetFlag = false);
596
597 public:
598 // CREATORS
599
600 /// Create a `MetricsManager`. Optionally specify a `basicAllocator`
601 /// used to supply memory. If `basicAllocator` is 0, the currently
602 /// installed default allocator is used.
603 explicit
604 MetricsManager(bslma::Allocator *basicAllocator = 0);
605
606 /// Destroy this `MetricsManager`.
608
609 // MANIPULATORS
610
611 /// Register the specified `callback` to collect records for the
612 /// category having the specified `categoryName`, and return an opaque
613 /// integer handle that can be used later to remove the `callback`.
614 /// The supplied `callback` will be called to collect metrics from the
615 /// identified category each time the category is published or
616 /// collected, even if the category is disabled. If the `publish` or
617 /// `collectSample` method is called on the identified category, and the
618 /// category is disabled, the `callback` will be invoked so clients may
619 /// update any internal state, but the collected metrics will be
620 /// ignored. Clients that wish to avoid overhead associated with
621 /// collecting metrics for a disabled category must test (within their
622 /// code) whether the category is disabled. The behavior is undefined
623 /// if the `callback` returns metrics belonging to metric categories
624 /// other than the one identified by `categoryName`, or if
625 /// `categoryName` is not null-terminated. Note that the same
626 /// `callback` can be registered for a category multiple times, and
627 /// that registering the same `callback` multiple times will result in
628 /// an equal number of invocations of the `callback` when publishing
629 /// the category.
631 const char *categoryName,
632 const RecordsCollectionCallback& callback);
633
634 /// Register the specified `callback` to collect records for the
635 /// specified `category`, and return an opaque integer handle that can
636 /// be used later to remove the `callback`. The supplied `callback`
637 /// will be called to collect metrics from `category` each time
638 /// `category` is published, even if `category` is disabled (i.e.,
639 /// `category->enabled()` is `false`). If the `publish` method is
640 /// called on `category` and `category` is disabled, the `callback` will
641 /// be invoked so clients may update any internal state, but the
642 /// collected metrics will be ignored. Clients that wish to avoid
643 /// overhead associated with collecting metrics for a disabled category
644 /// must test (within their code) whether the category is disabled. The
645 /// behavior is undefined if the `callback` returns metrics belonging to
646 /// metric categories other than `category`. Note that the same
647 /// `callback` can be registered for a `category` multiple times, and
648 /// that registering the same `callback` multiple times will result in
649 /// an equal number of invocations of the `callback` when publishing the
650 /// `category`.
652 const Category *category,
653 const RecordsCollectionCallback& callback);
654
655 /// Remove the callback associated with the specified `handle`. Return
656 /// 0 on success, or a non-zero value if `handle` cannot be found.
658
659 /// Add the specified `publisher` to the set of publishers that will be
660 /// used to propagate records for *every* category published by this
661 /// metrics manager. Return 0 on success, and a non-zero value with no
662 /// effect if `publisher` has already been registered. After this
663 /// method returns, *any* category published by this metrics manager
664 /// will be published to `publisher`. Note that this method will have
665 /// no effect and return a non-zero value if `publisher` was previously
666 /// registered for one or more specific categories (using the
667 /// alternative `addSpecificPublisher` method).
669
670 /// Add the specified `publisher` to the set of publishers that will be
671 /// used to publish metrics for the category identified by the
672 /// specified `categoryName`. Return 0 on success, and a non-zero
673 /// value with no effect if `publisher` has already been registered to
674 /// publish the identified category. The behavior is undefined unless
675 /// `categoryName` is null-terminated. Note that this method will fail
676 /// and return a non-zero value if `publisher` has previously been
677 /// registered to publish *every* category (using the alternative
678 /// `addGeneralPublisher` method).
679 int addSpecificPublisher(const char *categoryName,
680 const bsl::shared_ptr<Publisher>& publisher);
681
682 /// Add the specified `publisher` to the set of publishers that will be
683 /// used to publish metrics for the specified `category`. Return 0 on
684 /// success, and a non-zero value with no effect if `publisher` has
685 /// already been registered to publish `category`. The behavior is
686 /// undefined unless `category` is a valid address returned by the
687 /// `metricRegistry` method. Note that this method will fail and return
688 /// a non-zero value if `publisher` has previously been registered to
689 /// publish *every* category (using the alternative
690 /// `addGeneralPublisher` method).
691 int addSpecificPublisher(const Category *category,
692 const bsl::shared_ptr<Publisher>& publisher);
693
694 int removePublisher(const Publisher *publisher);
695 /// Stop publishing metrics to the specified `publisher` (for each
696 /// category), and remove it from this metrics manager. Return 0 on
697 /// success, and a non-zero value if `publisher` cannot be found.
699
700 /// Return a reference to the modifiable repository of collectors
701 /// managed by this object.
703
704 /// Return a reference to the modifiable registry of metrics managed by
705 /// this object.
707
710 bool resetFlag = false);
711 /// Load into the specified `sample` a metric sample collected from the
712 /// indicated categories, and append to `records` those collected
713 /// records which are referred to by `sample`. Optionally specify a
714 /// sequence of `categories` of length `numCategories`. If a sequence
715 /// of categories is not supplied, a sample is collected from all
716 /// registered categories. Optionally specify a `resetFlag` that
717 /// determines if the collected metrics are reset as part of this
718 /// operation. This operation will collect aggregated metric values
719 /// for each *enabled* category in the indicated categories from
720 /// registered callbacks as well as from its own `CollectorRepository`,
721 /// and then append those values to `records` and update `sample` with
722 /// the addresses of those collected `records`. If `resetFlag` is
723 /// `true`, the metrics being collected are reset to their default
724 /// state. This operation also populates the `sample` with the time
725 /// interval is computed as the elapsed time since the interval over
726 /// which the sampled metrics were collected. This last time the
727 /// metrics were reset (either through a call to the `publish` or
728 /// `collectSample` methods). If `category` has not previously been
729 /// reset then this interval is taken to be the elapsed time since the
730 /// creation of this metrics manager. The behavior is undefined unless
731 /// `0 <= numCategories`, `categories` refers to a contiguous sequence
732 /// of (at least) `numCategories`, and each category in `categories`
733 /// appears only once. Note that `sample` is loaded with the
734 /// *addresses* of the metric records appended to `records`, and
735 /// modifying `records` after this call returns may invalidate `sample`.
738 const Category * const categories[],
739 int numCategories,
740 bool resetFlag = false);
741
742 /// Publish metrics associated with the specified `category` if
743 /// `category` is enabled; otherwise (if `category` is not enabled)
744 /// this method has no effect. Optionally specify a `resetFlag` that
745 /// determines if the collected metrics are reset as part of this
746 /// operation. If `category` is enabled (i.e., `category->isEnabled()`
747 /// is `true`), this operation will collect aggregated metric values
748 /// for `category` from any registered callbacks as well as from its
749 /// own `CollectorRepository`, and then publish those records using any
750 /// publishers associated with `category`. If `resetFlag` is `true`,
751 /// the metrics being collected are reset to their default state. The
752 /// metrics manager provides publishers the time interval over which the
753 /// published metrics were collected. This interval is computed as the
754 /// elapsed time since the last time the `category` was reset (either
755 /// through a call to the `publish` or `collectSample` methods). If
756 /// `category` has not previously been reset then this interval is taken
757 /// to be the elapsed time since the creation of this metrics manager.
758 /// Note that the alternative `publish` methods that publish multiple
759 /// categories in a single invocation are more efficient than publishing
760 /// a sequence of categories individually.
761 void publish(const Category *category, bool resetFlag = true);
762
763 void publish(const Category *const categories[],
764 int numCategories,
765 bool resetFlag = true);
766
767 void publish(const bsl::set<const Category *>& categories,
768 bool resetFlag = true);
769 /// Publish metrics belonging to the specified sequence of (unique)
770 /// `categories`, of specified length `numCategories`. Optionally
771 /// specify a `resetFlag` that determines if the collected metrics are
772 /// reset as part of this operation. This operation will collect
773 /// aggregated metric values for each *enabled* category in `categories`
774 /// from registered callbacks as well as from its own
775 /// `CollectorRepository`, and then publish those records using any
776 /// publishers associated with the category. Any individual category in
777 /// `categories` that is not enabled is ignored. If `resetFlag` is
778 /// `true`, the metrics being collected are reset to their default
779 /// state. The metrics manager provides publishers the time interval
780 /// over which the published metrics were collected. This interval is
781 /// computed as the elapsed time since the last time the `category` was
782 /// reset (either through a call to the `publish` or `collectSample`
783 /// methods). If a category has not previously been reset then this
784 /// interval is taken to be the elapsed time since the creation of this
785 /// metrics manager. The behavior is undefined unless
786 /// `0 <= numCategories`, `categories` refers to a contiguous sequence
787 /// of (at least) `numCategories`, and each category in `categories`
788 /// appears only once.
789 void publish(const std::set<const Category *>& categories,
790 bool resetFlag = true);
791#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
792 void publish(const std::pmr::set<const Category *>& categories,
793 bool resetFlag = true);
794#endif
795 // Publish metrics belonging to the specified 'categories'.
796 // Optionally specify a 'resetFlag' that determines if the metrics are
797 // reset as part of this operation. This operation will collect
798 // aggregated metric values for each *enabled* category in 'categories'
799 // from registered callbacks as well as from its own
800 // 'CollectorRepository', and then publish those records using any
801 // publishers associated with the category. Any category in
802 // 'categories' that is not enabled is ignored. If 'resetFlag' is
803 // 'true', the metrics being collected are reset to their default
804 // state. The metrics manager provides publishers the time interval
805 // over which the published metrics were collected. This interval is
806 // computed as the elapsed time since the last time the 'category' was
807 // reset (either through a call to the 'publish' or 'collectSample'
808 // methods). If a category has not previously been reset then this
809 // interval is taken to be the elapsed time since the creation of this
810 // metrics manager.
811
812 void publishAll(bool resetFlag = true);
813
814 void publishAll(const bsl::set<const Category *>& excludedCategories,
815 bool resetFlag = true);
816 /// Publish metrics for every category registered with the contained
817 /// `MetricsRegistry` object. Optionally specify a `resetFlag` that
818 /// determines if the metrics are reset as part of this operation. This
819 /// operation will collect aggregated metric values for each enabled
820 /// category in its `metricRegistry()` from registered callbacks as well
821 /// as from its own `CollectorRepository`, and then publish those
822 /// records using any publishers associated with the category. Any
823 /// category that is not enabled is ignored. If `resetFlag` is `true`,
824 /// the metrics being collected are reset to their default state. The
825 /// metrics manager provides publishers the time interval over which a
826 /// published category of metrics were collected. This interval is
827 /// computed as the elapsed time since the last time the category was
828 /// reset (either through a call to the `publish` or `collectSample`
829 /// methods). If a category has not previously been reset then this
830 /// interval is taken to be the elapsed time since the creation of this
831 /// metrics manager.
832 void publishAll(const std::set<const Category *>& excludedCategories,
833 bool resetFlag = true);
834#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
835 void publishAll(const std::pmr::set<const Category *>& excludedCategories,
836 bool resetFlag = true);
837#endif
838 // Publish metrics for every category registered with the contained
839 // 'MetricsRegistry' object, except for the specified
840 // 'excludedCategories'. Optionally specify a 'resetFlag' that
841 // determines if the metrics are reset as part of this operation.
842 // This operation will collect aggregated metric values for each
843 // *enabled* category in its 'metricRegistry()' (that is not in
844 // 'excludedCategories') from registered callbacks as well as from its
845 // own 'CollectorRepository', and then publish those records using any
846 // publishers associated with the category. Any category that is not
847 // enabled is ignored. If 'resetFlag' is 'true', the metrics being
848 // collected are reset to their default state. The metrics manager
849 // provides publishers the time interval over which a published
850 // category of metrics were collected. This interval is computed as
851 // the elapsed time since the last time the category was reset (either
852 // through a call to the 'publish' or 'collectSample' methods). If a
853 // category has not previously been reset then this interval is taken
854 // to be the elapsed time since the creation of this metrics manager.
855
856 /// Set whether the specified `category` is enabled to the optionally
857 /// specified `isEnabled` value. If `category` has not been registered,
858 /// register it with the `metricRegistry()`. If a category is disabled
859 /// it will not be published (see the `publish` methods), and higher
860 /// level components may not record values for metrics belonging to the
861 /// category (for an example, see the @ref balm_metric documentation).
862 /// Note that this operation is *not* atomic, and other threads may
863 /// simultaneously access the current enabled value for `category` while
864 /// this operation is performed. Also note that this operation has
865 /// *linear* performance with respect to the number of registered
866 /// category holders for `category` (see @ref balm_metricregistry and
867 /// @ref balm_category for information on category holders).
868 void setCategoryEnabled(const char *category,
869 bool isEnabled = true);
870
871 /// Set whether the specified `category` is enabled to the optionally
872 /// specified `value`. If a category is disabled it will not be
873 /// published (see the `publish` methods), and higher level components
874 /// may not record values for metrics belonging to the category (for an
875 /// example, see the @ref balm_metric documentation). The behavior is
876 /// undefined unless `category` is a valid address of a category
877 /// previously returned by the metric registry owned by this
878 /// `MetricManager` object (i.e., `metricRegistry()`). Note that this
879 /// operation is thread-safe, but *not* atomic: Other threads may
880 /// simultaneously access the current enabled value for `category` while
881 /// this operation is performed. Also note that this operation has
882 /// *linear* performance with respect to the number of registered
883 /// category holders for `category` (see @ref balm_metricregistry and
884 /// @ref balm_category for information on category holders).
885 void setCategoryEnabled(const Category *category,
886 bool value = true);
887
888 /// Set whether each category currently registered with
889 /// `metricRegistry()` is enabled to the specified `value`, and ensure
890 /// that categories registered after this call are initialized as
891 /// either enabled or disabled, accordingly. If a category is disabled
892 /// it will not be published (see the `publish` methods), and higher
893 /// level components may not record values for metrics belonging to the
894 /// category (for an example, see the @ref balm_metric documentation).
895 /// This operation is logically equivalent to iterating over the list of
896 /// categories currently registered with `metricRegistry()` and calling
897 /// `setCategoryEnabled` on each category individually, and also setting
898 /// a default `isEnabled()` value (for newly-created categories).
899 /// Hence, subsequent calls to `setCategoryEnabled` will override this
900 /// value for a particular category. Note that this operation is
901 /// thread-safe, but *not* atomic: Other threads may simultaneously
902 /// access the current enabled status for a category while this
903 /// operation completes. Also note that this operation has *linear*
904 /// runtime performance with respect to the total number of category
905 /// holders registered with `metricRegistry()` (see
906 /// @ref balm_metricregistry and @ref balm_category for information on
907 /// category holders).
908 void setAllCategoriesEnabled(bool value);
909
910 // ACCESSORS
912 int findGeneralPublishers(std::vector<Publisher *> *publishers) const;
913#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
914 int findGeneralPublishers(std::pmr::vector<Publisher *> *publishers) const;
915#endif
916 // Append to the specified 'publishers' the addresses of publishers
917 // registered to publish metrics for every category. Return the number
918 // of publishers found. Note that this method will not find publishers
919 // associated with individual categories (i.e., category specific
920 // publishers).
921
923 const char *categoryName) const;
924 int findSpecificPublishers(std::vector<Publisher *> *publishers,
925 const char *categoryName) const;
926#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
928 std::pmr::vector<Publisher *> *publishers,
929 const char *categoryName) const;
930#endif
931 // Append to the specified 'publishers' the addresses of any
932 // publishers associated with the (particular) category identified by
933 // the specified 'categoryName'. Return the number of publishers
934 // found for the 'category'. The behavior is undefined unless
935 // 'category' is null-terminated. Note that this method will not find
936 // publishers registered for every category (i.e., general publishers)
937
939 const Category *category) const;
940 int findSpecificPublishers(std::vector<Publisher *> *publishers,
941 const Category *category) const;
942#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
943 int findSpecificPublishers(std::pmr::vector<Publisher *> *publishers,
944 const Category *category) const;
945#endif
946 // Append to the specified 'publishers' the addresses of any
947 // publishers associated with the (particular) specified 'category'.
948 // Return the number of publishers found for the 'category'. The
949 // behavior is undefined unless 'category' is a valid address supplied
950 // by 'metricRegistry()'. Note that this method will not find
951 // publishers registered for every category (i.e., general publishers).
952
953 /// Return a reference to the non-modifiable repository of collectors
954 /// managed by this object.
956
957 /// Return a reference to the non-modifiable registry of metrics managed
958 /// by this object.
959 const MetricRegistry& metricRegistry() const;
960};
961
962// ============================================================================
963// INLINE DEFINITIONS
964// ============================================================================
965
966 // --------------------
967 // class MetricsManager
968 // --------------------
969
970// MANIPULATORS
971inline
974 const char *categoryName,
975 const RecordsCollectionCallback& callback)
976{
978 d_metricRegistry.getCategory(categoryName),
979 callback);
980}
981
982inline
984 const char *categoryName,
985 const bsl::shared_ptr<Publisher>& publisher)
986{
987 return addSpecificPublisher(d_metricRegistry.getCategory(categoryName),
988 publisher);
989}
990
991inline
993 bool value)
994{
995 d_metricRegistry.setCategoryEnabled(category, value);
996}
997
998inline
999void MetricsManager::setCategoryEnabled(const char *category,
1000 bool isEnabled)
1001{
1002 d_metricRegistry.setCategoryEnabled(
1003 d_metricRegistry.getCategory(category), isEnabled);
1004}
1005
1006inline
1008{
1009 d_metricRegistry.setAllCategoriesEnabled(value);
1010}
1011
1012inline
1014{
1015 return d_collectors;
1016}
1017
1018inline
1020{
1021 return d_metricRegistry;
1022}
1023
1024// ACCESSORS
1025
1026inline
1028 bsl::vector<Publisher *> *publishers,
1029 const char *categoryName) const
1030{
1031 const Category *categoryPtr = d_metricRegistry.findCategory(categoryName);
1032 return categoryPtr ? findSpecificPublishers(publishers, categoryPtr) : 0;
1033}
1034
1035inline
1037 std::vector<Publisher *> *publishers,
1038 const char *categoryName) const
1039{
1040 const Category *categoryPtr = d_metricRegistry.findCategory(categoryName);
1041 return categoryPtr ? findSpecificPublishers(publishers, categoryPtr) : 0;
1042}
1043
1044#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
1045inline
1047 std::pmr::vector<Publisher *> *publishers,
1048 const char *categoryName) const
1049{
1050 const Category *categoryPtr = d_metricRegistry.findCategory(categoryName);
1051 return categoryPtr ? findSpecificPublishers(publishers, categoryPtr) : 0;
1052}
1053#endif
1054
1055inline
1056const CollectorRepository&
1058{
1059 return d_collectors;
1060}
1061
1062inline
1064{
1065 return d_metricRegistry;
1066}
1067
1068} // close package namespace
1069
1070
1071#endif
1072
1073// ----------------------------------------------------------------------------
1074// Copyright 2015 Bloomberg Finance L.P.
1075//
1076// Licensed under the Apache License, Version 2.0 (the "License");
1077// you may not use this file except in compliance with the License.
1078// You may obtain a copy of the License at
1079//
1080// http://www.apache.org/licenses/LICENSE-2.0
1081//
1082// Unless required by applicable law or agreed to in writing, software
1083// distributed under the License is distributed on an "AS IS" BASIS,
1084// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1085// See the License for the specific language governing permissions and
1086// limitations under the License.
1087// ----------------------------- END-OF-FILE ----------------------------------
1088
1089/** @} */
1090/** @} */
1091/** @} */
Definition balm_category.h:151
Definition balm_collectorrepository.h:184
Definition balm_metricregistry.h:180
void setCategoryEnabled(const Category *category, bool value)
const Category * getCategory(const char *category)
void setAllCategoriesEnabled(bool value)
const Category * findCategory(const char *category) const
Definition balm_metricsample.h:342
Definition balm_metricsmanager.h:490
MetricsManager(bslma::Allocator *basicAllocator=0)
bsl::function< void(bsl::vector< MetricRecord > *, bool)> RecordsCollectionCallback
Definition balm_metricsmanager.h:506
CallbackHandle registerCollectionCallback(const Category *category, const RecordsCollectionCallback &callback)
void setAllCategoriesEnabled(bool value)
Definition balm_metricsmanager.h:1007
int CallbackHandle
Identifies a registered RecordsCollectionCallback.
Definition balm_metricsmanager.h:509
int findGeneralPublishers(bsl::vector< Publisher * > *publishers) const
int addSpecificPublisher(const char *categoryName, const bsl::shared_ptr< Publisher > &publisher)
Definition balm_metricsmanager.h:983
int addGeneralPublisher(const bsl::shared_ptr< Publisher > &publisher)
int findSpecificPublishers(bsl::vector< Publisher * > *publishers, const Category *category) const
int removePublisher(const Publisher *publisher)
void collectSample(MetricSample *sample, bsl::vector< MetricRecord > *records, bool resetFlag=false)
void publish(const Category *category, bool resetFlag=true)
@ BAEM_INVALID_HANDLE
Definition balm_metricsmanager.h:559
@ e_INVALID_HANDLE
Definition balm_metricsmanager.h:557
void publish(const bsl::set< const Category * > &categories, bool resetFlag=true)
~MetricsManager()
Destroy this MetricsManager.
void publish(const Category *const categories[], int numCategories, bool resetFlag=true)
CollectorRepository & collectorRepository()
Definition balm_metricsmanager.h:1013
int findGeneralPublishers(std::vector< Publisher * > *publishers) const
int removePublisher(const bsl::shared_ptr< Publisher > &publisher)
int removeCollectionCallback(CallbackHandle handle)
void publishAll(bool resetFlag=true)
void publish(const std::set< const Category * > &categories, bool resetFlag=true)
void publishAll(const std::set< const Category * > &excludedCategories, bool resetFlag=true)
MetricRegistry & metricRegistry()
Definition balm_metricsmanager.h:1019
void publishAll(const bsl::set< const Category * > &excludedCategories, bool resetFlag=true)
int findSpecificPublishers(std::vector< Publisher * > *publishers, const Category *category) const
void setCategoryEnabled(const char *category, bool isEnabled=true)
Definition balm_metricsmanager.h:999
void collectSample(MetricSample *sample, bsl::vector< MetricRecord > *records, const Category *const categories[], int numCategories, bool resetFlag=false)
friend struct MetricsManager_PublicationHelper
Definition balm_metricsmanager.h:547
int findSpecificPublishers(bsl::vector< Publisher * > *publishers, const char *categoryName) const
Definition balm_metricsmanager.h:1027
CallbackHandle registerCollectionCallback(const char *categoryName, const RecordsCollectionCallback &callback)
Definition balm_metricsmanager.h:973
BSLMF_NESTED_TRAIT_DECLARATION(MetricsManager, bslma::UsesBslmaAllocator)
int addSpecificPublisher(const Category *category, const bsl::shared_ptr< Publisher > &publisher)
Definition balm_publisher.h:276
Forward declaration.
Definition bslstl_function.h:934
Definition bslstl_map.h:619
Definition bslstl_set.h:657
Definition bslstl_sharedptr.h:1830
Definition bslstl_vector.h:1025
Definition bslma_allocator.h:457
Definition bslma_managedptr.h:1182
Definition bslmt_mutex.h:315
Definition bslmt_rwmutex.h:147
Definition bsls_timeinterval.h:301
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balm_bdlmmetricsadapter.h:141
Definition bslma_usesbslmaallocator.h:343