BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balm_publicationscheduler.h
Go to the documentation of this file.
1/// @file balm_publicationscheduler.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balm_publicationscheduler.h -*-C++-*-
8#ifndef INCLUDED_BALM_PUBLICATIONSCHEDULER
9#define INCLUDED_BALM_PUBLICATIONSCHEDULER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balm_publicationscheduler balm_publicationscheduler
15/// @brief Provide a scheduler for publishing metrics.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balm
19/// @{
20/// @addtogroup balm_publicationscheduler
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balm_publicationscheduler-purpose"> Purpose</a>
25/// * <a href="#balm_publicationscheduler-classes"> Classes </a>
26/// * <a href="#balm_publicationscheduler-description"> Description </a>
27/// * <a href="#balm_publicationscheduler-alternative-systems-for-telemetry"> Alternative Systems for Telemetry </a>
28/// * <a href="#balm_publicationscheduler-thread-safety"> Thread Safety </a>
29/// * <a href="#balm_publicationscheduler-usage"> Usage </a>
30/// * <a href="#balm_publicationscheduler-example-1-basic-usage"> Example 1: Basic Usage </a>
31///
32/// # Purpose {#balm_publicationscheduler-purpose}
33/// Provide a scheduler for publishing metrics.
34///
35/// # Classes {#balm_publicationscheduler-classes}
36///
37/// - balm::PublicationScheduler: a scheduler for publishing metrics
38///
39/// @see balm_metricsmanager
40///
41/// # Description {#balm_publicationscheduler-description}
42/// This component defines a class, `balm::PublicationScheduler`,
43/// that provides a scheduling mechanism for the publication of metrics. At
44/// construction, a `balm::PublicationScheduler` is provided the addresses of a
45/// `balm::MetricsManager` and a `bdlmt::TimerEventScheduler`. The publication
46/// scheduler provides a `scheduleCategory` method that schedules an individual
47/// metric category to be published repeatedly at a given interval, and a
48/// `setDefaultSchedule` method that schedules the publication of any category
49/// not given an individual schedule. The `balm::PublicationScheduler` creates
50/// timer events using the `bdlmt::TimerEventScheduler`. At the end of a
51/// scheduled time interval, the publication scheduler invokes the metrics
52/// manager's `publish` operation with the set of categories to publish. Note
53/// that the publication scheduler will combine categories that occur at the
54/// same frequency into a single invocation of the metrics manager's `publish`
55/// operation. The publication scheduler also provides a method to cancel the
56/// publication of a particular category, or of all categories.
57///
58/// ## Alternative Systems for Telemetry {#balm_publicationscheduler-alternative-systems-for-telemetry}
59///
60///
61/// Bloomberg software may alternatively use the GUTS telemetry API, which is
62/// integrated into Bloomberg infrastructure.
63///
64/// ## Thread Safety {#balm_publicationscheduler-thread-safety}
65///
66///
67/// `balm::PublicationScheduler` is fully *thread-safe*, meaning that all
68/// non-creator operations on a given instance can be safely invoked
69/// simultaneously from multiple threads.
70///
71/// ## Usage {#balm_publicationscheduler-usage}
72///
73///
74/// This section illustrates intended use of this component.
75///
76/// ### Example 1: Basic Usage {#balm_publicationscheduler-example-1-basic-usage}
77///
78///
79/// The following example demonstrates how to use `balm::PublicationScheduler`.
80/// Before instantiating the publication scheduler, we create a
81/// `bdlmt::TimerEventScheduler` as well as a `balm::MetricsManager`. We obtain
82/// collectors for three different metric categories, "A", "B", and "C", that
83/// we will use to generate metric values for publication.
84/// @code
85/// bslma::Allocator *allocator = bslma::Default::allocator(0);
86/// bdlmt::TimerEventScheduler timer(allocator);
87/// balm::MetricsManager manager(allocator);
88///
89/// balm::Collector *A = manager.collectorRepository().getDefaultCollector(
90/// "A", "a");
91/// balm::Collector *B = manager.collectorRepository().getDefaultCollector(
92/// "B", "b");
93/// balm::Collector *C = manager.collectorRepository().getDefaultCollector(
94/// "C", "c");
95/// @endcode
96/// We now create an instance of `SimpleStreamPublisher`, which implements the
97/// `balm::Publisher` protocol. Note that `SimpleStreamPublisher` is an
98/// example implementation of the `balm::Publisher` protocol defined in the
99/// @ref balm_publisher component. In practice, clients typically use a standard
100/// publisher class (e.g., `balm::StreamPublisher`).
101/// @code
102/// bsl::shared_ptr<balm::Publisher> publisher(
103/// new (*allocator) SimpleStreamPublisher(bsl::cout),
104/// allocator);
105/// @endcode
106/// We now register the `publisher` we have created with the metrics `manager`
107/// to publish our categories. Then, we `start` the timer-event scheduler we
108/// will supply to the `balm::PublicationScheduler`.
109/// @code
110/// manager.addGeneralPublisher(publisher);
111/// timer.start();
112/// @endcode
113/// Now we construct a `balm::PublicationScheduler` and pass it the respective
114/// addresses of both the metrics manager and the timer-event scheduler. We
115/// schedule the publication of category "A" and "B" every .05 seconds, then we
116/// set the scheduled default publication to every .10 seconds. Note that those
117/// time intervals were chosen to ensure fast and consistent output for this
118/// example. In normal usage the interval between publications should be large
119/// enough to ensure that metric publication does not negatively affect the
120/// performance of the application (a 30 second interval is typical).
121/// @code
122/// balm::PublicationScheduler scheduler(&manager, &timer, allocator);
123/// scheduler.scheduleCategory("A", bsls::TimeInterval(.05));
124/// scheduler.scheduleCategory("B", bsls::TimeInterval(.05));
125/// scheduler.setDefaultSchedule(bsls::TimeInterval(.10));
126/// @endcode
127/// We can use the accessor operations to verify the schedule that we have
128/// specified.
129/// @code
130/// bsls::TimeInterval intervalA, intervalB, intervalC, defaultInterval;
131/// assert( scheduler.findCategorySchedule(&intervalA, "A"));
132/// assert( scheduler.findCategorySchedule(&intervalB, "B"));
133/// assert(!scheduler.findCategorySchedule(&intervalC, "C"));
134/// assert( scheduler.getDefaultSchedule(&defaultInterval));
135///
136/// assert(bsls::TimeInterval(.05) == intervalA);
137/// assert(bsls::TimeInterval(.05) == intervalB);
138/// assert(bsls::TimeInterval(.10) == defaultInterval);
139/// @endcode
140/// Finally we add a couple of metrics and wait just over .1 seconds.
141/// @code
142/// A->update(1.0);
143/// B->update(2.0);
144/// C->update(3.0);
145/// bslmt::ThreadUtil::sleep(bsls::TimeInterval(.11));
146/// @endcode
147/// The output of the publication should look similar to:
148/// @code
149/// 19NOV2008_18:34:26.766+0000 2 Records 0.0517s Elapsed Time
150/// A.a [count = 1, total = 1, min = 1, max = 1]
151/// B.b [count = 1, total = 2, min = 2, max = 2]
152/// 19NOV2008_18:34:26.816+0000 2 Records 0.050183s Elapsed Time
153/// A.a [count = 0, total = 0, min = inf, max = -inf]
154/// B.b [count = 0, total = 0, min = inf, max = -inf]
155/// 19NOV2008_18:34:26.817+0000 1 Records 0.102473s Elapsed Time
156/// C.c [count = 1, total = 3, min = 3, max = 3]
157/// @endcode
158/// Note that category `C` is published as part of the scheduled default
159/// publication. Also note that categories `A` and `B` are emitted as a single
160/// publication: the scheduler combines categories published at the same
161/// frequency into a single publication event to minimize the number of times
162/// `balm::MetricsManager::publish` is invoked.
163/// @}
164/** @} */
165/** @} */
166
167/** @addtogroup bal
168 * @{
169 */
170/** @addtogroup balm
171 * @{
172 */
173/** @addtogroup balm_publicationscheduler
174 * @{
175 */
176
177#include <balscm_version.h>
178
179#include <balm_metricsmanager.h>
180
181#include <bslmt_mutex.h>
182
184
185#include <bsls_timeinterval.h>
186
187#include <bslma_allocator.h>
188
190
191#include <bsl_iosfwd.h>
192#include <bsl_map.h>
193#include <bsl_memory.h>
194#include <bsl_set.h>
195#include <bsl_utility.h>
196#include <bsl_vector.h>
197
198#include <bsls_libraryfeatures.h>
199
200#include <vector> // 'std::vector', 'std::pmr::vector'
201
202
203
204
205namespace balm {
206
207class Category;
208
209class PublicationScheduler_ClockData; // defined in implementation
210class PublicationScheduler_Proctor; // defined in implementation
211
212 // ==========================
213 // class PublicationScheduler
214 // ==========================
215
216/// This class defines a mechanism for scheduling the periodic publication
217/// of metrics. Each publication scheduler object is supplied the address
218/// of a `MetricsManager` and a `bdlmt::TimerEventScheduler` at
219/// construction. The metrics manager is used to publish metrics, while
220/// the timer-event scheduler provides the underlying scheduling mechanism.
221/// Metrics are scheduled for publication using the `scheduleCategory` and
222/// `setDefaultSchedule` methods. The `scheduleCategory` method schedules
223/// an individual category to be publisher periodically at the provided
224/// interval, whereas `setDefaultSchedule` schedules the periodic
225/// publication of any category not given an individual schedule. The
226/// publication scheduler will create a recurring timer for each unique
227/// time interval supplied, and will group together categories that share a
228/// common time interval into a single call to `MetricsManager::publish`.
229///
230/// \note Note that it is left unspecified whether publication events that occur
231/// on a common multiple of *different* intervals will be grouped into a
232/// single invocation of `MetricsManager::publish`.
233///
234/// See @ref balm_publicationscheduler
236
237 // PRIVATE TYPES
238
239 /// A private implementation type holding the data for a scheduled
240 /// publication frequency (e.g., the set of categories published at that
241 /// frequency). Each "clock" created in the underlying
242 /// `bdlmt::TimerEventScheduler` is associated with a `ClockData`
243 /// object.
244 typedef PublicationScheduler_ClockData ClockData;
245
246 /// A map from a category to the publication interval for that
247 /// category.
249
250 /// A map from a time interval (i.e., publication period) to the clock
251 /// information for that time interval.
254
255 // DATA
256 bdlmt::TimerEventScheduler *d_scheduler_p; // event scheduler (held)
257
258 MetricsManager *d_manager_p; // metrics manager (held)
259
260 Categories d_categories; // map of category => schedule
261
262 Clocks d_clocks; // map of interval => clock
263 // info
264
265 bsls::TimeInterval d_defaultInterval;
266 // default publication interval
267
268 mutable bslmt::Mutex d_mutex; // synchronize access to data
269 // ('d_categories', 'd_clocks',
270 // and 'd_defaultInterval')
271
272 bslma::Allocator *d_allocator_p; // allocator (held, not owned)
273
274 private:
275 // NOT IMPLEMENTED
277 PublicationScheduler& operator=(const PublicationScheduler& );
278
279 // FRIENDS
281
282 // PRIVATE MANIPULATORS
283
284 /// Publish, to the held `MetricsManager` object, the categories indicated by the specified `clockData`.
285 ///
286 /// \note Note that this operation
287 /// serves as the event callback provided to the underlying
288 /// `bdlmt::TimerEventScheduler`: this method is bound with a
289 /// `ClockData` object in the `bsl::function` objects provided to
290 /// `d_scheduler_p`.
291 void publish(bsl::shared_ptr<ClockData> clockData);
292
293 /// Cancel the periodic publication of the category indicated by the
294 /// specified `categoryIterator`. Any scheduled publication of the
295 /// indicated category is either canceled or completed before this method returns.
296 ///
297 /// \pre The behavior is undefined unless
298 /// `categoryIterator` is a valid iterator over `d_categories` and
299 /// `d_mutex` is *locked*.
300 void cancelCategory(Categories::iterator categoryIterator);
301
302 /// If the default publication schedule has been set (using
303 /// `setDefaultSchedule`), cancel that periodic default publication,
304 /// and return 0. This method has no effect and will return a non-zero
305 /// value if a default publication schedule has not been set. Any
306 /// scheduled publication is either canceled or completed before this method returns.
307 ///
308 /// \pre The behavior is undefined unless `d_mutex` is
309 /// *locked*.
310 int cancelDefaultSchedule();
311
312 public:
313 // TRAITS
316
317 // CREATORS
318
319 /// Create a publication scheduler that will use the specified
320 /// `metricsManager` to publish metrics, and the specified
321 /// `eventScheduler` to supply timer events. Optionally specify a
322 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
323 /// the currently installed default allocator is used.
325 bdlmt::TimerEventScheduler *eventScheduler,
326 bslma::Allocator *basicAllocator = 0);
327
328 /// Destroy this publication scheduler and cancel any pending publications.
329 ///
330 /// \note Note that, if any metrics are currently being
331 /// published, this operation will block until all of their
332 /// publications have completed.
334
335 // MANIPULATORS
336
337 /// Schedule the specified null-terminated string `category` to be
338 /// published periodically at the specified `interval` using the
339 /// `MetricManager` supplied at construction. If `category` has
340 /// *already* been scheduled, change the scheduled period to `interval`;
341 /// any previously scheduled publication of `category` is either
342 /// canceled or completed (atomically) prior to rescheduling. If a
343 /// category is rescheduled with the same `interval` as it is currently
344 /// scheduled, this operation has no effect.
345 ///
346 /// \pre The behavior is undefined unless `bsls::TimeInterval(0, 0) < interval`.
347 void scheduleCategory(const char *category,
348 const bsls::TimeInterval& interval);
349
350 /// Schedule the specified `category` to be published periodically at
351 /// the specified `interval` using the `MetricManager` supplied at
352 /// construction. If `category` has *already* been scheduled, change
353 /// the scheduled period to `interval`; any previously scheduled
354 /// publication of `category` is either canceled or completed
355 /// (atomically) prior to rescheduling. If a category is rescheduled
356 /// with the same `interval` as it is currently scheduled, this operation has no effect.
357 ///
358 /// \pre The behavior is undefined unless
359 /// `bsls::TimeInterval(0, 0) < interval` and `category` is a valid
360 /// address supplied by the `balm::MetricRegistry` owned by the
361 /// `MetricsManager` object supplied at construction.
362 void scheduleCategory(const Category *category,
363 const bsls::TimeInterval& interval);
364
365 /// Set, to the specified `interval`, the default interval for metrics
366 /// to be periodically published using the `MetricsManager` supplied at
367 /// construction. This method schedules every metric category not given
368 /// a individual schedule (using `scheduleCategory`), to be published
369 /// periodically until that category is either given an individual
370 /// schedule, or the default schedule is canceled (using either
371 /// `clearDefaultSchedule` or `cancelAllPublications`). If a default
372 /// publication has *already* been scheduled, change its schedule to
373 /// `interval`; any previously scheduled publication is either canceled
374 /// or completed (atomically) before rescheduling. If the default
375 /// publication is rescheduled with the same `interval` as it is
376 /// currently scheduled, this operation has no effect.
377 ///
378 /// \pre The behavior is undefined unless `bsls::TimeInterval(0, 0) < interval`.
379 ///
380 /// \note Note that, to exclude a category from any publication, clients can disable the
381 /// category using the `MetricsManager` object supplied at construction.
383
384 /// Cancel the periodic publication of the specified null-terminated
385 /// string `category`. Return 0 on success, and a non-zero value if the
386 /// `category` is not scheduled for publication. Any scheduled
387 /// publication of `category` is either canceled or completed before this method returns.
388 ///
389 /// \note Note that if a default publication schedule
390 /// has been set (using `setDefaultSchedule`), then `category` will
391 /// continue to be published as part of that scheduled default
392 /// publication; to exclude a category from any publication, clients
393 /// can disable the category using the `MetricsManager` object supplied
394 /// at construction.
395 int cancelCategorySchedule(const char *category);
396
397 /// Cancel the periodic publication of the specified `category`. Return
398 /// 0 on success, and a non-zero value if the `category` is not
399 /// scheduled for publication. Any scheduled publication of `category`
400 /// is either canceled or completed before this method returns.
401 ///
402 /// \pre The behavior is undefined unless `category` is a valid address supplied
403 /// by the `balm::MetricRegistry` owned by `metricsManager`.
404 ///
405 /// \note Note that if a default publication schedule has been set (using
406 /// `setDefaultSchedule`), then `category` will continue to be published
407 /// as part of that scheduled default publication; to exclude a category
408 /// from any publication, clients can disable the category using the
409 /// `MetricsManager` object supplied at construction.
410 int cancelCategorySchedule(const Category *category);
411
412 /// If the default publication schedule has been set (using
413 /// `setDefaultSchedule`), cancel that periodic default publication, and
414 /// return 0. This method has no effect and will return a non-zero
415 /// value if a default publication schedule has not been set. Any
416 /// scheduled publication is either canceled or completed before this
417 /// method returns.
419
420 /// Cancel all periodic publication of metrics. This operation
421 /// (atomically) clears the default publication schedule and cancels the
422 /// publication schedule of any category individually scheduled using
423 /// the `scheduleCategory` method. Any scheduled publication is either
424 /// canceled or completed before this method returns.
425 void cancelAll();
426
427 /// Return the address of the modifiable metrics manager for which this
428 /// publication scheduler publishes metrics.
430
431 // ACCESSORS
432
433 /// Load into the specified `result` the individual schedule interval
434 /// (set using the `scheduleCategory` method) that corresponds to the
435 /// specified null-terminated string `category`, if found, and return
436 /// `true`, or (if not found) return `false` with no effect. This
437 /// method will return `false` and will not modify `result` if
438 /// `category` is published as part of the default scheduled
439 /// publication.
441 const char *category) const;
442
443 /// Load into the specified `result` the individual schedule interval
444 /// (set using the `scheduleCategory` method) that corresponds to the
445 /// specified `category`, if found, and return `true`, or (if not
446 /// found) return `false` with no effect. This method will return
447 /// `false` and will not modify `result` if `category` is published as
448 /// part of the default scheduled publication.
449 ///
450 /// \pre The behavior is undefined unless `category` is a valid address supplied by the
451 /// `balm::MetricRegistry` owned by the `MetricsManager` object
452 /// supplied at construction.
454 const Category *category) const;
455
456 /// Load into the specified `result` the default scheduled interval,
457 /// (set using the `setDefaultSchedule` method), for periodically
458 /// publishing metrics, if found, and return `true`, or (if not found)
459 /// return `false` with no effect.
461
464 bsls::TimeInterval> > *result) const;
466 std::vector<std::pair<const Category *,
467 bsls::TimeInterval> > *result) const;
468#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
470 std::pmr::vector<std::pair<const Category *,
471 bsls::TimeInterval>> *result) const;
472#endif
473 // Load into the specified 'result' a representation of the current
474 // schedule for publishing categories being followed by this scheduler
475 // and return the number of scheduled categories. The schedule is
476 // represented using a series of (category address, time interval)
477 // pairs; each pair in the series indicates the periodic time interval
478 // that the associated category will be published. Note that the
479 // 'result' of this operation contains only those categories scheduled
480 // using the 'scheduleCategory' operation, and does *not* include
481 // categories published as part of the default publication.
482
483 /// Return the address of the non-modifiable metrics manager for which
484 /// this publication scheduler will publish metrics.
485 const MetricsManager *manager() const;
486
487 /// Print a formatted string describing the current state of this
488 /// `PublicationScheduler` object to the specified `stream` at the
489 /// (absolute value of) the optionally specified indentation `level`
490 /// and return a reference to `stream`. If `level` is specified,
491 /// optionally specify `spacesPerLevel`, the number of spaces per
492 /// indentation level for this and all of its nested objects. If
493 /// `level` is negative, suppress indentation of the first line. If
494 /// `spacesPerLevel` is negative, suppress all indentation AND format
495 /// the entire output on one line. If `stream` is not valid on entry, this operation has no effect.
496 ///
497 /// \note Note that this is provided primarily
498 /// for debugging purposes.
499 bsl::ostream& print(bsl::ostream& stream,
500 int level = 0,
501 int spacesPerLevel = 4) const;
502};
503
504// ============================================================================
505// INLINE DEFINITIONS
506// ============================================================================
507
508 // --------------------------
509 // class PublicationScheduler
510 // --------------------------
511
512// MANIPULATORS
513inline
515{
516 return d_manager_p;
517}
518
519inline
521 const char *category,
522 const bsls::TimeInterval& interval)
523{
524 scheduleCategory(d_manager_p->metricRegistry().getCategory(category),
525 interval);
526}
527
528inline
530{
532 d_manager_p->metricRegistry().getCategory(category));
533}
534
535// ACCESSORS
536inline
538{
539 return d_manager_p;
540}
541
542inline
544 bsls::TimeInterval *result,
545 const char *category) const
546{
548 result,
549 d_manager_p->metricRegistry().getCategory(category));
550}
551
552} // close package namespace
553
554
555#endif
556
557// ----------------------------------------------------------------------------
558// Copyright 2015 Bloomberg Finance L.P.
559//
560// Licensed under the Apache License, Version 2.0 (the "License");
561// you may not use this file except in compliance with the License.
562// You may obtain a copy of the License at
563//
564// http://www.apache.org/licenses/LICENSE-2.0
565//
566// Unless required by applicable law or agreed to in writing, software
567// distributed under the License is distributed on an "AS IS" BASIS,
568// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
569// See the License for the specific language governing permissions and
570// limitations under the License.
571// ----------------------------- END-OF-FILE ----------------------------------
572
573/** @} */
574/** @} */
575/** @} */
Definition balm_category.h:152
const Category * getCategory(const char *category)
Definition balm_metricsmanager.h:490
MetricRegistry & metricRegistry()
Definition balm_metricsmanager.h:1038
Definition balm_publicationscheduler.h:235
bool getDefaultSchedule(bsls::TimeInterval *result) const
friend class PublicationScheduler_Proctor
Definition balm_publicationscheduler.h:280
PublicationScheduler(MetricsManager *metricsManager, bdlmt::TimerEventScheduler *eventScheduler, bslma::Allocator *basicAllocator=0)
bool findCategorySchedule(bsls::TimeInterval *result, const char *category) const
Definition balm_publicationscheduler.h:543
void scheduleCategory(const Category *category, const bsls::TimeInterval &interval)
MetricsManager * manager()
Definition balm_publicationscheduler.h:514
int cancelCategorySchedule(const Category *category)
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
int cancelCategorySchedule(const char *category)
Definition balm_publicationscheduler.h:529
int getCategorySchedule(std::vector< std::pair< const Category *, bsls::TimeInterval > > *result) const
BSLMF_NESTED_TRAIT_DECLARATION(PublicationScheduler, bslma::UsesBslmaAllocator)
void scheduleCategory(const char *category, const bsls::TimeInterval &interval)
Definition balm_publicationscheduler.h:520
bool findCategorySchedule(bsls::TimeInterval *result, const Category *category) const
void setDefaultSchedule(const bsls::TimeInterval &interval)
int getCategorySchedule(bsl::vector< bsl::pair< const Category *, bsls::TimeInterval > > *result) const
Definition bdlmt_timereventscheduler.h:445
Definition bslstl_map.h:653
BloombergLP::bslstl::TreeIterator< value_type, Node, difference_type > iterator
Definition bslstl_map.h:756
Definition bslstl_pair.h:1280
Definition bslstl_sharedptr.h:1838
Definition bslstl_vector.h:1120
Definition bslma_allocator.h:545
Definition bslmt_mutex.h:317
Definition bsls_timeinterval.h:307
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition balm_bdlmmetricsadapter.h:142
Definition bslma_usesbslmaallocator.h:344