BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balm_stopwatchscopedguard.h
Go to the documentation of this file.
1/// @file balm_stopwatchscopedguard.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balm_stopwatchscopedguard.h -*-C++-*-
8#ifndef INCLUDED_BALM_STOPWATCHSCOPEDGUARD
9#define INCLUDED_BALM_STOPWATCHSCOPEDGUARD
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup balm_stopwatchscopedguard balm_stopwatchscopedguard
15/// @brief Provide a scoped guard for recording elapsed time.
16/// @addtogroup bal
17/// @{
18/// @addtogroup balm
19/// @{
20/// @addtogroup balm_stopwatchscopedguard
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#balm_stopwatchscopedguard-purpose"> Purpose</a>
25/// * <a href="#balm_stopwatchscopedguard-classes"> Classes </a>
26/// * <a href="#balm_stopwatchscopedguard-description"> Description </a>
27/// * <a href="#balm_stopwatchscopedguard-alternative-systems-for-telemetry"> Alternative Systems for Telemetry </a>
28/// * <a href="#balm_stopwatchscopedguard-choosing-between-balm-stopwatchscopedguard-and-macros"> Choosing Between balm::StopwatchScopedGuard and Macros </a>
29/// * <a href="#balm_stopwatchscopedguard-thread-safety"> Thread Safety </a>
30/// * <a href="#balm_stopwatchscopedguard-usage"> Usage </a>
31/// * <a href="#balm_stopwatchscopedguard-example-1-create-and-configure-the-default-balm-metricsmanager-instance"> Example 1: Create and Configure the Default balm::MetricsManager Instance </a>
32/// * <a href="#balm_stopwatchscopedguard-example-2-metric-collection-with-balm-stopwatchscopedguard"> Example 2: Metric Collection with balm::StopwatchScopedGuard </a>
33///
34/// # Purpose {#balm_stopwatchscopedguard-purpose}
35/// Provide a scoped guard for recording elapsed time.
36///
37/// # Classes {#balm_stopwatchscopedguard-classes}
38///
39/// - balm::StopwatchScopedGuard: guard for recording a metric for elapsed time
40///
41/// @see balm_metricsmanager, balm_defaultmetricsmanager, balm_metric
42///
43/// # Description {#balm_stopwatchscopedguard-description}
44/// This component provides a scoped guard class intended to
45/// simplify the task of recording (to a metric) the elapsed time of a block of
46/// code. The `balm::StopwatchScopedGuard` is supplied the identity of a metric
47/// on construction, and an optional enumerated constant indicating the time
48/// units to report values in (by default, values are reported in seconds). The
49/// guard measures the elapsed time between its construction and destruction,
50/// and on destruction records that elapsed time, in the indicated time units,
51/// to the supplied metric.
52///
53/// ## Alternative Systems for Telemetry {#balm_stopwatchscopedguard-alternative-systems-for-telemetry}
54///
55///
56/// Bloomberg software may alternatively use the GUTS telemetry API, which is
57/// integrated into Bloomberg infrastructure.
58///
59/// ## Choosing Between balm::StopwatchScopedGuard and Macros {#balm_stopwatchscopedguard-choosing-between-balm-stopwatchscopedguard-and-macros}
60///
61///
62/// The `balm::StopwatchScopedGuard` class and the macros defined in the
63/// @ref balm_metrics component provide the same basic functionality. Clients may
64/// find that using a `balm::StopwatchScopedGuard` object (in coordination with
65/// a `balm::Metric` object) is better suited to collecting metrics associated
66/// with a particular instance of a stateful object, while macros are better
67/// suited to collecting metrics associated with a particular code path (rather
68/// than an object instance). In most instances, however, choosing between the
69/// two is a matter of taste.
70///
71/// ## Thread Safety {#balm_stopwatchscopedguard-thread-safety}
72///
73///
74/// `balm::StopwatchScopedGuard` is *const* *thread-safe*, meaning that
75/// accessors may be invoked concurrently from different threads, but it is not
76/// safe to access or modify a `balm::StopwatchScopedGuard` in one thread while
77/// thread modifies the same object. Note however, that at this another time
78/// `balm::StopwatchScopedGuard` provides no manipulator methods.
79///
80/// ## Usage {#balm_stopwatchscopedguard-usage}
81///
82///
83/// This section illustrates intended use of this component.
84///
85/// ### Example 1: Create and Configure the Default balm::MetricsManager Instance {#balm_stopwatchscopedguard-example-1-create-and-configure-the-default-balm-metricsmanager-instance}
86///
87///
88/// This example demonstrates how to create the default `balm::MetricManager`
89/// instance and perform a trivial configuration.
90///
91/// First we create a `balm::DefaultMetricsManagerScopedGuard`, which manages
92/// the lifetime of the default metrics manager instance. At construction, we
93/// provide the scoped guard an output stream (`stdout`) that it will publish
94/// metrics to. Note that the default metrics manager is intended to be created
95/// and destroyed by the *owner* of `main`. An instance of the manager should
96/// be created during the initialization of an application (while the task has a
97/// single thread) and destroyed just prior to termination (when there is
98/// similarly a single thread).
99/// @code
100/// int main(int argc, char *argv[])
101/// {
102///
103/// // ...
104///
105/// balm::DefaultMetricsManagerScopedGuard managerGuard(bsl::cout);
106/// @endcode
107/// Once the default instance has been created, it can be accessed using the
108/// `instance` operation:
109/// @code
110/// balm::MetricsManager *manager = balm::DefaultMetricsManager::instance();
111/// assert(0 != manager);
112/// @endcode
113/// Note that the default metrics manager will be released when `managerGuard`
114/// exits this scoped and is destroyed. Clients that choose to explicitly call
115/// the `balm::DefaultMetricsManager::create` method must also explicitly call
116/// the `balm::DefaultMetricsManager::release` method.
117///
118/// ### Example 2: Metric Collection with balm::StopwatchScopedGuard {#balm_stopwatchscopedguard-example-2-metric-collection-with-balm-stopwatchscopedguard}
119///
120///
121/// Alternatively, we can use the `balm::StopwatchScopedGuard` to record metric
122/// values. In the following example we implement a hypothetical request
123/// processor similar to the one in example 3. We use a `balm::Metric`
124/// (`d_elapsedTime`) and a `balm::StopwatchScopedGuard` (`guard`) to record the
125/// elapsed time of the request-processing function.
126/// @code
127/// class RequestProcessor {
128///
129/// // DATA
130/// balm::Metric d_elapsedTime;
131///
132/// public:
133///
134/// // CREATORS
135/// RequestProcessor()
136/// : d_elapsedTime("MyCategory", "RequestProcessor/elapsedTime")
137/// {}
138///
139/// // MANIPULATORS
140/// int processRequest(const bsl::string& request)
141/// // Process the specified 'request'. Return 0 on success, and a
142/// // non-zero value otherwise.
143/// {
144/// (void)request;
145///
146/// int returnCode = 0;
147///
148/// balm::StopwatchScopedGuard guard(&d_elapsedTime);
149///
150/// // ...
151///
152/// return returnCode;
153/// }
154///
155/// // ...
156/// };
157///
158/// // ...
159///
160/// RequestProcessor processor;
161///
162/// processor.processRequest("ab");
163/// processor.processRequest("abc");
164/// processor.processRequest("abc");
165/// processor.processRequest("abdef");
166///
167/// manager->publishAll();
168///
169/// processor.processRequest("ab");
170/// processor.processRequest("abc");
171/// processor.processRequest("abc");
172/// processor.processRequest("abdef");
173///
174/// processor.processRequest("a");
175/// processor.processRequest("abc");
176/// processor.processRequest("abc");
177/// processor.processRequest("abdefg");
178///
179/// manager->publishAll();
180///
181/// @endcode
182/// @}
183/** @} */
184/** @} */
185
186/** @addtogroup bal
187 * @{
188 */
189/** @addtogroup balm
190 * @{
191 */
192/** @addtogroup balm_stopwatchscopedguard
193 * @{
194 */
195
196#include <balscm_version.h>
197
198#include <balm_collector.h>
201#include <balm_metric.h>
202#include <balm_metricsmanager.h>
203
204#include <bsls_platform.h>
205#include <bsls_stopwatch.h>
206
207
208
209namespace balm {
210 // ==========================
211 // class StopwatchScopedGuard
212 // ==========================
213
214/// This class provides a mechanism for recording, to a metric, the elapsed
215/// time from the construction of an instance of the guard until that
216/// instance goes out of scope (and is destroyed). The constructor of this
217/// class takes an optional argument indicating the time units in which to
218/// report the elapsed time; by default a guard will report time in seconds.
219/// The supplied time units determine the scale of the double value reported
220/// by this guard, but does *not* affect the precision of the elapsed time
221/// measurement. Each instance of this class delegates to a `Collector` for
222/// the metric. This `Collector` is initialized on construction based on
223/// the constructor arguments. If this scoped guard is not initialized with
224/// an active metric, or if the supplied metric becomes inactive before the
225/// scoped guard is destroyed, then `isActive()` will return `false` and no metric values will be recorded.
226///
227/// \note Note that if the metric supplied at
228/// construction is not active when the scoped guard is constructed, the
229/// scoped guard will not become active or record metric values regardless
230/// of the future state of that supplied metric.
231///
232/// See @ref balm_stopwatchscopedguard
234
235 public:
236 // PUBLIC TYPES
237 enum Units {
238 // An enumeration of supported time units.
239
240 k_NANOSECONDS = 1000000000,
241 k_MICROSECONDS = 1000000,
243 k_SECONDS = 1
244#ifndef BDE_OMIT_INTERNAL_DEPRECATED
253#endif // BDE_OMIT_INTERNAL_DEPRECATED
254 };
255
256 private:
257 // DATA
258 bsls::Stopwatch d_stopwatch; // stopwatch
259
260 Units d_timeUnits; // time units to record elapsed time in
261
262 Collector *d_collector_p; // metric collector (held, not owned); may
263 // be 0, but cannot be invalid
264
265 private:
266 // NOT IMPLEMENTED
269
270 public:
271 // CREATORS
272
273 /// Initialize this scoped guard to record elapsed time using the
274 /// specified `metric`. Optionally specify the `timeUnits` in which to
275 /// report elapsed time. If `metric->isActive()` is `false`, this
276 /// object will also be inactive (i.e., will not record any values).
277 ///
278 /// \pre The behavior is undefined unless `metric` is a valid address of a `Metric` object.
279 ///
280 /// \note Note that `timeUnits` indicates the scale of the
281 /// double value reported by this guard, but does *not* affect the
282 /// precision of the elapsed time measurement.
283 explicit StopwatchScopedGuard(Metric *metric,
284 Units timeUnits = k_SECONDS);
285
286 /// Initialize this scoped guard to record elapsed time using the
287 /// specified `collector`. Optionally specify the `timeUnits` in which
288 /// to report elapsed time. If `collector` is 0 or
289 ///`collector->category().enabled() == false`, this object will be
290 /// inactive (i.e., will not record any values).
291 ///
292 /// \pre The behavior is undefined unless
293 /// `collector == 0 || collector->metricId().isValid()`.
294 ///
295 /// \note Note that `timeUnits` indicates the scale of the double value reported by
296 /// this guard, but does *not* affect the precision of the elapsed time
297 /// measurement.
298 explicit StopwatchScopedGuard(Collector *collector,
299 Units timeUnits = k_SECONDS);
300
301 /// Initialize this scoped guard to record an elapsed time to the
302 /// specified `metricId` from the optionally specified `manager`.
303 /// Optionally specify the `timeUnits` in which to report elapsed time.
304 /// If `timeUnits` is not provided, the elapsed time will be reported in
305 /// seconds. If `manager` is 0, the `DefaultMetricsManager` singleton
306 /// instance is used. If no `manager` is supplied and the default
307 /// instance has not been created, this object will be inactive (i.e.,
308 /// it will not record any values); similarly, if the metric's
309 /// associated category is disabled (i.e.,
310 /// `metricId.category()->enabled()` is `false`), then this object will be inactive.
311 ///
312 /// \pre The behavior is undefined unless unless `metricId` is
313 /// a valid id returned by the `MetricRepository` object owned by the indicated metrics manager.
314 ///
315 /// \note Note that `timeUnits` indicates the
316 /// scale of the double value reported by this guard, but does *not*
317 /// affect the precision of the elapsed time measurement.
318 StopwatchScopedGuard(const MetricId& metricId,
319 MetricsManager *manager = 0);
320 StopwatchScopedGuard(const MetricId& metricId,
321 Units timeUnits,
322 MetricsManager *manager = 0);
323
324 /// Initialize this scoped guard to record an elapsed time to the
325 /// metric, identified by the specified `category` and `name`, from the
326 /// optionally specified `manager`. Optionally specify the `timeUnits`
327 /// in which to report elapsed time. If `timeUnits` is not provided,
328 /// the elapsed time will be reported in seconds. If `manager` is 0,
329 /// use the `DefaultMetricsManager` instance. If no `manager` is
330 /// supplied, and the default instance has not been created, this
331 /// object will be inactive (i.e., it will not record any values);
332 /// similarly, if the identified `category` is disabled, then this object will be inactive.
333 ///
334 /// \pre The behavior is undefined unless `category` and `name` are null-terminated.
335 ///
336 /// \note Note that `timeUnits`
337 /// indicates the scale of the double value reported by this guard, but
338 /// does *not* affect the precision of the elapsed time measurement.
339 StopwatchScopedGuard(const char *category,
340 const char *name,
341 MetricsManager *manager = 0);
342 StopwatchScopedGuard(const char *category,
343 const char *name,
344 Units timeUnits,
345 MetricsManager *manager = 0);
346
347 /// Destroy this scoped guard and, if the scoped guard is active,
348 /// record the accumulated elapsed time from its creation..
350
351 // ACCESSORS
352
353 /// Return `true` if this scoped guard will actively record metrics, and
354 /// `false` otherwise. If the returned value is `false` the destructor
355 /// will not record a value to the metric. A scoped guard will be
356 /// inactive if either (1) it was not initialized with a valid metric,
357 /// (2) the metric it was initialized with was not active at the time
358 /// of construction, or (3) the metric supplied at construction is
359 /// currently inactive, meaning the category of metrics this metric
360 /// belongs to has been disabled since this object's construction (see
361 /// the `MetricsManager` method `setCategoryEnabled`).
362 bool isActive() const;
363};
364
365// ============================================================================
366// INLINE DEFINITIONS
367// ============================================================================
368
369 // --------------------------
370 // class StopwatchScopedGuard
371 // --------------------------
372
373// CREATORS
374inline
375StopwatchScopedGuard::StopwatchScopedGuard(Metric *metric,
376 Units timeUnits)
377: d_stopwatch()
378, d_timeUnits(timeUnits)
379, d_collector_p(metric->isActive() ? metric->collector() : 0)
380{
381 if (d_collector_p) {
382 d_stopwatch.start();
383 }
384}
385
386inline
387StopwatchScopedGuard::StopwatchScopedGuard(Collector *collector,
388 Units timeUnits)
389: d_stopwatch()
390, d_timeUnits(timeUnits)
391, d_collector_p((collector && collector->metricId().category()->enabled())
392 ? collector
393 : 0)
394{
395 if (d_collector_p) {
396 d_stopwatch.start();
397 }
398}
399
400inline
401StopwatchScopedGuard::StopwatchScopedGuard(const MetricId& metricId,
402 MetricsManager *manager)
403: d_stopwatch()
404, d_timeUnits(k_SECONDS)
405, d_collector_p(0)
406{
407 Collector *collector = Metric::lookupCollector(metricId, manager);
408 d_collector_p = (collector &&
409 collector->metricId().category()->enabled())
410 ? collector : 0;
411 if (d_collector_p) {
412 d_stopwatch.start();
413 }
414}
415
416inline
417StopwatchScopedGuard::StopwatchScopedGuard(const MetricId& metricId,
418 Units timeUnits,
419 MetricsManager *manager)
420: d_stopwatch()
421, d_timeUnits(timeUnits)
422, d_collector_p(0)
423{
424 Collector *collector = Metric::lookupCollector(metricId, manager);
425 d_collector_p = (collector &&
426 collector->metricId().category()->enabled())
427 ? collector : 0;
428 if (d_collector_p) {
429 d_stopwatch.start();
430 }
431}
432
433inline
434StopwatchScopedGuard::StopwatchScopedGuard(const char *category,
435 const char *name,
436 MetricsManager *manager)
437: d_stopwatch()
438, d_timeUnits(k_SECONDS)
439, d_collector_p(0)
440{
441 Collector *collector = Metric::lookupCollector(category, name, manager);
442
443 d_collector_p = (collector &&
444 collector->metricId().category()->enabled())
445 ? collector : 0;
446
447 if (d_collector_p) {
448 d_stopwatch.start();
449 }
450}
451
452inline
453StopwatchScopedGuard::StopwatchScopedGuard(const char *category,
454 const char *name,
455 Units timeUnits,
456 MetricsManager *manager)
457: d_stopwatch()
458, d_timeUnits(timeUnits)
459, d_collector_p(0)
460{
461 Collector *collector = Metric::lookupCollector(category, name, manager);
462 d_collector_p = (collector && collector->metricId().category()->enabled())
463 ? collector : 0;
464 if (d_collector_p) {
465 d_stopwatch.start();
466 }
467}
468
469inline
471{
472 if (isActive()) {
473 d_collector_p->update(d_stopwatch.elapsedTime() * +d_timeUnits);
474 }
475}
476
477// ACCESSORS
478inline
480{
481 return 0 != d_collector_p
482 && d_collector_p->metricId().category()->enabled();
483}
484
485} // close package namespace
486
487
488#endif
489
490// ----------------------------------------------------------------------------
491// Copyright 2015 Bloomberg Finance L.P.
492//
493// Licensed under the Apache License, Version 2.0 (the "License");
494// you may not use this file except in compliance with the License.
495// You may obtain a copy of the License at
496//
497// http://www.apache.org/licenses/LICENSE-2.0
498//
499// Unless required by applicable law or agreed to in writing, software
500// distributed under the License is distributed on an "AS IS" BASIS,
501// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
502// See the License for the specific language governing permissions and
503// limitations under the License.
504// ----------------------------- END-OF-FILE ----------------------------------
505
506/** @} */
507/** @} */
508/** @} */
bool enabled() const
Definition balm_category.h:359
Definition balm_collector.h:152
const MetricId & metricId() const
Definition balm_collector.h:310
void update(double value)
Definition balm_collector.h:273
Definition balm_metricid.h:162
const Category * category() const
Definition balm_metricid.h:330
Definition balm_metric.h:251
static Collector * lookupCollector(const char *category, const char *name, MetricsManager *manager=0)
Definition balm_metric.h:468
Definition balm_metricsmanager.h:490
Definition balm_stopwatchscopedguard.h:233
~StopwatchScopedGuard()
Definition balm_stopwatchscopedguard.h:470
Units
Definition balm_stopwatchscopedguard.h:237
@ k_MICROSECONDS
Definition balm_stopwatchscopedguard.h:241
@ BAEM_NANOSECONDS
Definition balm_stopwatchscopedguard.h:245
@ BAEM_MICROSECONDS
Definition balm_stopwatchscopedguard.h:246
@ MICROSECONDS
Definition balm_stopwatchscopedguard.h:250
@ BAEM_MILLISECONDS
Definition balm_stopwatchscopedguard.h:247
@ SECONDS
Definition balm_stopwatchscopedguard.h:252
@ BAEM_SECONDS
Definition balm_stopwatchscopedguard.h:248
@ NANOSECONDS
Definition balm_stopwatchscopedguard.h:249
@ k_SECONDS
Definition balm_stopwatchscopedguard.h:243
@ k_MILLISECONDS
Definition balm_stopwatchscopedguard.h:242
@ k_NANOSECONDS
Definition balm_stopwatchscopedguard.h:240
@ MILLISECONDS
Definition balm_stopwatchscopedguard.h:251
bool isActive() const
Definition balm_stopwatchscopedguard.h:479
Definition bsls_stopwatch.h:149
void start(bool collectCpuTimes=false)
Definition bsls_stopwatch.h:354
double elapsedTime() const
Definition bsls_stopwatch.h:433
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition balm_bdlmmetricsadapter.h:142