BDE 4.14.0 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/// Note that it is left unspecified whether publication events that occur
230/// on a common multiple of *different* intervals will be grouped into a
231/// single invocation of `MetricsManager::publish`.
232///
233/// See @ref balm_publicationscheduler
235
236 // PRIVATE TYPES
237
238 /// A private implementation type holding the data for a scheduled
239 /// publication frequency (e.g., the set of categories published at that
240 /// frequency). Each "clock" created in the underlying
241 /// `bdlmt::TimerEventScheduler` is associated with a `ClockData`
242 /// object.
243 typedef PublicationScheduler_ClockData ClockData;
244
245 /// A map from a category to the publication interval for that
246 /// category.
248
249 /// A map from a time interval (i.e., publication period) to the clock
250 /// information for that time interval.
253
254 // DATA
255 bdlmt::TimerEventScheduler *d_scheduler_p; // event scheduler (held)
256
257 MetricsManager *d_manager_p; // metrics manager (held)
258
259 Categories d_categories; // map of category => schedule
260
261 Clocks d_clocks; // map of interval => clock
262 // info
263
264 bsls::TimeInterval d_defaultInterval;
265 // default publication interval
266
267 mutable bslmt::Mutex d_mutex; // synchronize access to data
268 // ('d_categories', 'd_clocks',
269 // and 'd_defaultInterval')
270
271 bslma::Allocator *d_allocator_p; // allocator (held, not owned)
272
273 private:
274 // NOT IMPLEMENTED
276 PublicationScheduler& operator=(const PublicationScheduler& );
277
278 // FRIENDS
280
281 // PRIVATE MANIPULATORS
282
283 /// Publish, to the held `MetricsManager` object, the categories
284 /// indicated by the specified `clockData`. Note that this operation
285 /// serves as the event callback provided to the underlying
286 /// `bdlmt::TimerEventScheduler`: this method is bound with a
287 /// `ClockData` object in the `bsl::function` objects provided to
288 /// `d_scheduler_p`.
289 void publish(bsl::shared_ptr<ClockData> clockData);
290
291 /// Cancel the periodic publication of the category indicated by the
292 /// specified `categoryIterator`. Any scheduled publication of the
293 /// indicated category is either canceled or completed before this
294 /// method returns. The behavior is undefined unless
295 /// `categoryIterator` is a valid iterator over `d_categories` and
296 /// `d_mutex` is *locked*.
297 void cancelCategory(Categories::iterator categoryIterator);
298
299 /// If the default publication schedule has been set (using
300 /// `setDefaultSchedule`), cancel that periodic default publication,
301 /// and return 0. This method has no effect and will return a non-zero
302 /// value if a default publication schedule has not been set. Any
303 /// scheduled publication is either canceled or completed before this
304 /// method returns. The behavior is undefined unless `d_mutex` is
305 /// *locked*.
306 int cancelDefaultSchedule();
307
308 public:
309 // TRAITS
312
313 // CREATORS
314
315 /// Create a publication scheduler that will use the specified
316 /// `metricsManager` to publish metrics, and the specified
317 /// `eventScheduler` to supply timer events. Optionally specify a
318 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
319 /// the currently installed default allocator is used.
321 bdlmt::TimerEventScheduler *eventScheduler,
322 bslma::Allocator *basicAllocator = 0);
323
324 /// Destroy this publication scheduler and cancel any pending
325 /// publications. Note that, if any metrics are currently being
326 /// published, this operation will block until all of their
327 /// publications have completed.
329
330 // MANIPULATORS
331
332 /// Schedule the specified null-terminated string `category` to be
333 /// published periodically at the specified `interval` using the
334 /// `MetricManager` supplied at construction. If `category` has
335 /// *already* been scheduled, change the scheduled period to `interval`;
336 /// any previously scheduled publication of `category` is either
337 /// canceled or completed (atomically) prior to rescheduling. If a
338 /// category is rescheduled with the same `interval` as it is currently
339 /// scheduled, this operation has no effect. The behavior is undefined
340 /// unless `bsls::TimeInterval(0, 0) < interval`.
341 void scheduleCategory(const char *category,
342 const bsls::TimeInterval& interval);
343
344 /// Schedule the specified `category` to be published periodically at
345 /// the specified `interval` using the `MetricManager` supplied at
346 /// construction. If `category` has *already* been scheduled, change
347 /// the scheduled period to `interval`; any previously scheduled
348 /// publication of `category` is either canceled or completed
349 /// (atomically) prior to rescheduling. If a category is rescheduled
350 /// with the same `interval` as it is currently scheduled, this
351 /// operation has no effect. The behavior is undefined unless
352 /// `bsls::TimeInterval(0, 0) < interval` and `category` is a valid
353 /// address supplied by the `balm::MetricRegistry` owned by the
354 /// `MetricsManager` object supplied at construction.
355 void scheduleCategory(const Category *category,
356 const bsls::TimeInterval& interval);
357
358 /// Set, to the specified `interval`, the default interval for metrics
359 /// to be periodically published using the `MetricsManager` supplied at
360 /// construction. This method schedules every metric category not given
361 /// a individual schedule (using `scheduleCategory`), to be published
362 /// periodically until that category is either given an individual
363 /// schedule, or the default schedule is canceled (using either
364 /// `clearDefaultSchedule` or `cancelAllPublications`). If a default
365 /// publication has *already* been scheduled, change its schedule to
366 /// `interval`; any previously scheduled publication is either canceled
367 /// or completed (atomically) before rescheduling. If the default
368 /// publication is rescheduled with the same `interval` as it is
369 /// currently scheduled, this operation has no effect. The behavior is
370 /// undefined unless `bsls::TimeInterval(0, 0) < interval`. Note that,
371 /// to exclude a category from any publication, clients can disable the
372 /// category using the `MetricsManager` object supplied at construction.
374
375 /// Cancel the periodic publication of the specified null-terminated
376 /// string `category`. Return 0 on success, and a non-zero value if the
377 /// `category` is not scheduled for publication. Any scheduled
378 /// publication of `category` is either canceled or completed before
379 /// this method returns. Note that if a default publication schedule
380 /// has been set (using `setDefaultSchedule`), then `category` will
381 /// continue to be published as part of that scheduled default
382 /// publication; to exclude a category from any publication, clients
383 /// can disable the category using the `MetricsManager` object supplied
384 /// at construction.
385 int cancelCategorySchedule(const char *category);
386
387 /// Cancel the periodic publication of the specified `category`. Return
388 /// 0 on success, and a non-zero value if the `category` is not
389 /// scheduled for publication. Any scheduled publication of `category`
390 /// is either canceled or completed before this method returns. The
391 /// behavior is undefined unless `category` is a valid address supplied
392 /// by the `balm::MetricRegistry` owned by `metricsManager`. Note that
393 /// if a default publication schedule has been set (using
394 /// `setDefaultSchedule`), then `category` will continue to be published
395 /// as part of that scheduled default publication; to exclude a category
396 /// from any publication, clients can disable the category using the
397 /// `MetricsManager` object supplied at construction.
398 int cancelCategorySchedule(const Category *category);
399
400 /// If the default publication schedule has been set (using
401 /// `setDefaultSchedule`), cancel that periodic default publication, and
402 /// return 0. This method has no effect and will return a non-zero
403 /// value if a default publication schedule has not been set. Any
404 /// scheduled publication is either canceled or completed before this
405 /// method returns.
407
408 /// Cancel all periodic publication of metrics. This operation
409 /// (atomically) clears the default publication schedule and cancels the
410 /// publication schedule of any category individually scheduled using
411 /// the `scheduleCategory` method. Any scheduled publication is either
412 /// canceled or completed before this method returns.
413 void cancelAll();
414
415 /// Return the address of the modifiable metrics manager for which this
416 /// publication scheduler publishes metrics.
418
419 // ACCESSORS
420
421 /// Load into the specified `result` the individual schedule interval
422 /// (set using the `scheduleCategory` method) that corresponds to the
423 /// specified null-terminated string `category`, if found, and return
424 /// `true`, or (if not found) return `false` with no effect. This
425 /// method will return `false` and will not modify `result` if
426 /// `category` is published as part of the default scheduled
427 /// publication.
429 const char *category) const;
430
431 /// Load into the specified `result` the individual schedule interval
432 /// (set using the `scheduleCategory` method) that corresponds to the
433 /// specified `category`, if found, and return `true`, or (if not
434 /// found) return `false` with no effect. This method will return
435 /// `false` and will not modify `result` if `category` is published as
436 /// part of the default scheduled publication. The behavior is
437 /// undefined unless `category` is a valid address supplied by the
438 /// `balm::MetricRegistry` owned by the `MetricsManager` object
439 /// supplied at construction.
441 const Category *category) const;
442
443 /// Load into the specified `result` the default scheduled interval,
444 /// (set using the `setDefaultSchedule` method), for periodically
445 /// publishing metrics, if found, and return `true`, or (if not found)
446 /// return `false` with no effect.
448
451 bsls::TimeInterval> > *result) const;
453 std::vector<std::pair<const Category *,
454 bsls::TimeInterval> > *result) const;
455#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR
457 std::pmr::vector<std::pair<const Category *,
458 bsls::TimeInterval>> *result) const;
459#endif
460 // Load into the specified 'result' a representation of the current
461 // schedule for publishing categories being followed by this scheduler
462 // and return the number of scheduled categories. The schedule is
463 // represented using a series of (category address, time interval)
464 // pairs; each pair in the series indicates the periodic time interval
465 // that the associated category will be published. Note that the
466 // 'result' of this operation contains only those categories scheduled
467 // using the 'scheduleCategory' operation, and does *not* include
468 // categories published as part of the default publication.
469
470 /// Return the address of the non-modifiable metrics manager for which
471 /// this publication scheduler will publish metrics.
472 const MetricsManager *manager() const;
473
474 /// Print a formatted string describing the current state of this
475 /// `PublicationScheduler` object to the specified `stream` at the
476 /// (absolute value of) the optionally specified indentation `level`
477 /// and return a reference to `stream`. If `level` is specified,
478 /// optionally specify `spacesPerLevel`, the number of spaces per
479 /// indentation level for this and all of its nested objects. If
480 /// `level` is negative, suppress indentation of the first line. If
481 /// `spacesPerLevel` is negative, suppress all indentation AND format
482 /// the entire output on one line. If `stream` is not valid on entry,
483 /// this operation has no effect. Note that this is provided primarily
484 /// for debugging purposes.
485 bsl::ostream& print(bsl::ostream& stream,
486 int level = 0,
487 int spacesPerLevel = 4) const;
488};
489
490// ============================================================================
491// INLINE DEFINITIONS
492// ============================================================================
493
494 // --------------------------
495 // class PublicationScheduler
496 // --------------------------
497
498// MANIPULATORS
499inline
501{
502 return d_manager_p;
503}
504
505inline
507 const char *category,
508 const bsls::TimeInterval& interval)
509{
510 scheduleCategory(d_manager_p->metricRegistry().getCategory(category),
511 interval);
512}
513
514inline
516{
518 d_manager_p->metricRegistry().getCategory(category));
519}
520
521// ACCESSORS
522inline
524{
525 return d_manager_p;
526}
527
528inline
530 bsls::TimeInterval *result,
531 const char *category) const
532{
534 result,
535 d_manager_p->metricRegistry().getCategory(category));
536}
537
538} // close package namespace
539
540
541#endif
542
543// ----------------------------------------------------------------------------
544// Copyright 2015 Bloomberg Finance L.P.
545//
546// Licensed under the Apache License, Version 2.0 (the "License");
547// you may not use this file except in compliance with the License.
548// You may obtain a copy of the License at
549//
550// http://www.apache.org/licenses/LICENSE-2.0
551//
552// Unless required by applicable law or agreed to in writing, software
553// distributed under the License is distributed on an "AS IS" BASIS,
554// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
555// See the License for the specific language governing permissions and
556// limitations under the License.
557// ----------------------------- END-OF-FILE ----------------------------------
558
559/** @} */
560/** @} */
561/** @} */
Definition balm_category.h:151
const Category * getCategory(const char *category)
Definition balm_metricsmanager.h:490
MetricRegistry & metricRegistry()
Definition balm_metricsmanager.h:1019
Definition balm_publicationscheduler.h:234
bool getDefaultSchedule(bsls::TimeInterval *result) const
friend class PublicationScheduler_Proctor
Definition balm_publicationscheduler.h:279
PublicationScheduler(MetricsManager *metricsManager, bdlmt::TimerEventScheduler *eventScheduler, bslma::Allocator *basicAllocator=0)
bool findCategorySchedule(bsls::TimeInterval *result, const char *category) const
Definition balm_publicationscheduler.h:529
void scheduleCategory(const Category *category, const bsls::TimeInterval &interval)
MetricsManager * manager()
Definition balm_publicationscheduler.h:500
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:515
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:506
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:434
Definition bslstl_map.h:619
BloombergLP::bslstl::TreeIterator< value_type, Node, difference_type > iterator
Definition bslstl_map.h:722
Definition bslstl_pair.h:1210
Definition bslstl_sharedptr.h:1830
Definition bslstl_vector.h:1025
Definition bslma_allocator.h:457
Definition bslmt_mutex.h:315
Definition bsls_timeinterval.h:301
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balm_bdlmmetricsadapter.h:141
Definition bslma_usesbslmaallocator.h:343