BDE 4.14.0 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
226/// metric values will be recorded. Note that if the metric supplied at
227/// construction is not active when the scoped guard is constructed, the
228/// scoped guard will not become active or record metric values regardless
229/// of the future state of that supplied metric.
230///
231/// See @ref balm_stopwatchscopedguard
233
234 public:
235 // PUBLIC TYPES
236 enum Units {
237 // An enumeration of supported time units.
238
239 k_NANOSECONDS = 1000000000,
240 k_MICROSECONDS = 1000000,
242 k_SECONDS = 1
243#ifndef BDE_OMIT_INTERNAL_DEPRECATED
252#endif // BDE_OMIT_INTERNAL_DEPRECATED
253 };
254
255 private:
256 // DATA
257 bsls::Stopwatch d_stopwatch; // stopwatch
258
259 Units d_timeUnits; // time units to record elapsed time in
260
261 Collector *d_collector_p; // metric collector (held, not owned); may
262 // be 0, but cannot be invalid
263
264 // NOT IMPLEMENTED
267
268 public:
269 // CREATORS
270
271 /// Initialize this scoped guard to record elapsed time using the
272 /// specified `metric`. Optionally specify the `timeUnits` in which to
273 /// report elapsed time. If `metric->isActive()` is `false`, this
274 /// object will also be inactive (i.e., will not record any values).
275 /// The behavior is undefined unless `metric` is a valid address of a
276 /// `Metric` object. Note that `timeUnits` indicates the scale of the
277 /// double value reported by this guard, but does *not* affect the
278 /// precision of the elapsed time measurement.
279 explicit StopwatchScopedGuard(Metric *metric,
280 Units timeUnits = k_SECONDS);
281
282 /// Initialize this scoped guard to record elapsed time using the
283 /// specified `collector`. Optionally specify the `timeUnits` in which
284 /// to report elapsed time. If `collector` is 0 or
285 ///`collector->category().enabled() == false`, this object will be
286 /// inactive (i.e., will not record any values). The behavior is
287 /// undefined unless
288 /// `collector == 0 || collector->metricId().isValid()`. Note that
289 /// `timeUnits` indicates the scale of the double value reported by
290 /// this guard, but does *not* affect the precision of the elapsed time
291 /// measurement.
292 explicit StopwatchScopedGuard(Collector *collector,
293 Units timeUnits = k_SECONDS);
294
295 StopwatchScopedGuard(const MetricId& metricId,
296 MetricsManager *manager = 0);
297 /// Initialize this scoped guard to record an elapsed time to the
298 /// specified `metricId` from the optionally specified `manager`.
299 /// Optionally specify the `timeUnits` in which to report elapsed time.
300 /// If `timeUnits` is not provided, the elapsed time will be reported in
301 /// seconds. If `manager` is 0, the `DefaultMetricsManager` singleton
302 /// instance is used. If no `manager` is supplied and the default
303 /// instance has not been created, this object will be inactive (i.e.,
304 /// it will not record any values); similarly, if the metric's
305 /// associated category is disabled (i.e.,
306 /// `metricId.category()->enabled()` is `false`), then this object will
307 /// be inactive. The behavior is undefined unless unless `metricId` is
308 /// a valid id returned by the `MetricRepository` object owned by the
309 /// indicated metrics manager. Note that `timeUnits` indicates the
310 /// scale of the double value reported by this guard, but does *not*
311 /// affect the precision of the elapsed time measurement.
312 StopwatchScopedGuard(const MetricId& metricId,
313 Units timeUnits,
314 MetricsManager *manager = 0);
315
316 StopwatchScopedGuard(const char *category,
317 const char *name,
318 MetricsManager *manager = 0);
319 /// Initialize this scoped guard to record an elapsed time to the
320 /// metric, identified by the specified `category` and `name`, from the
321 /// optionally specified `manager`. Optionally specify the `timeUnits`
322 /// in which to report elapsed time. If `timeUnits` is not provided,
323 /// the elapsed time will be reported in seconds. If `manager` is 0,
324 /// use the `DefaultMetricsManager` instance. If no `manager` is
325 /// supplied, and the default instance has not been created, this
326 /// object will be inactive (i.e., it will not record any values);
327 /// similarly, if the identified `category` is disabled, then this
328 /// object will be inactive. The behavior is undefined unless
329 /// `category` and `name` are null-terminated. Note that `timeUnits`
330 /// indicates the scale of the double value reported by this guard, but
331 /// does *not* affect the precision of the elapsed time measurement.
332 StopwatchScopedGuard(const char *category,
333 const char *name,
334 Units timeUnits,
335 MetricsManager *manager = 0);
336
337 /// Destroy this scoped guard and, if the scoped guard is active,
338 /// record the accumulated elapsed time from its creation..
340
341 // ACCESSORS
342
343 /// Return `true` if this scoped guard will actively record metrics, and
344 /// `false` otherwise. If the returned value is `false` the destructor
345 /// will not record a value to the metric. A scoped guard will be
346 /// inactive if either (1) it was not initialized with a valid metric,
347 /// (2) the metric it was initialized with was not active at the time
348 /// of construction, or (3) the metric supplied at construction is
349 /// currently inactive, meaning the category of metrics this metric
350 /// belongs to has been disabled since this object's construction (see
351 /// the `MetricsManager` method `setCategoryEnabled`).
352 bool isActive() const;
353};
354
355// ============================================================================
356// INLINE DEFINITIONS
357// ============================================================================
358
359 // --------------------------
360 // class StopwatchScopedGuard
361 // --------------------------
362
363// CREATORS
364inline
365StopwatchScopedGuard::StopwatchScopedGuard(Metric *metric,
366 Units timeUnits)
367: d_stopwatch()
368, d_timeUnits(timeUnits)
369, d_collector_p(metric->isActive() ? metric->collector() : 0)
370{
371 if (d_collector_p) {
372 d_stopwatch.start();
373 }
374}
375
376inline
377StopwatchScopedGuard::StopwatchScopedGuard(Collector *collector,
378 Units timeUnits)
379: d_stopwatch()
380, d_timeUnits(timeUnits)
381, d_collector_p((collector && collector->metricId().category()->enabled())
382 ? collector
383 : 0)
384{
385 if (d_collector_p) {
386 d_stopwatch.start();
387 }
388}
389
390inline
391StopwatchScopedGuard::StopwatchScopedGuard(const MetricId& metricId,
392 MetricsManager *manager)
393: d_stopwatch()
394, d_timeUnits(k_SECONDS)
395, d_collector_p(0)
396{
397 Collector *collector = Metric::lookupCollector(metricId, manager);
398 d_collector_p = (collector &&
399 collector->metricId().category()->enabled())
400 ? collector : 0;
401 if (d_collector_p) {
402 d_stopwatch.start();
403 }
404}
405
406inline
407StopwatchScopedGuard::StopwatchScopedGuard(const MetricId& metricId,
408 Units timeUnits,
409 MetricsManager *manager)
410: d_stopwatch()
411, d_timeUnits(timeUnits)
412, d_collector_p(0)
413{
414 Collector *collector = Metric::lookupCollector(metricId, manager);
415 d_collector_p = (collector &&
416 collector->metricId().category()->enabled())
417 ? collector : 0;
418 if (d_collector_p) {
419 d_stopwatch.start();
420 }
421}
422
423inline
424StopwatchScopedGuard::StopwatchScopedGuard(const char *category,
425 const char *name,
426 MetricsManager *manager)
427: d_stopwatch()
428, d_timeUnits(k_SECONDS)
429, d_collector_p(0)
430{
431 Collector *collector = Metric::lookupCollector(category, name, manager);
432
433 d_collector_p = (collector &&
434 collector->metricId().category()->enabled())
435 ? collector : 0;
436
437 if (d_collector_p) {
438 d_stopwatch.start();
439 }
440}
441
442inline
443StopwatchScopedGuard::StopwatchScopedGuard(const char *category,
444 const char *name,
445 Units timeUnits,
446 MetricsManager *manager)
447: d_stopwatch()
448, d_timeUnits(timeUnits)
449, d_collector_p(0)
450{
451 Collector *collector = Metric::lookupCollector(category, name, manager);
452 d_collector_p = (collector && collector->metricId().category()->enabled())
453 ? collector : 0;
454 if (d_collector_p) {
455 d_stopwatch.start();
456 }
457}
458
459inline
461{
462 if (isActive()) {
463 d_collector_p->update(d_stopwatch.elapsedTime() * +d_timeUnits);
464 }
465}
466
467// ACCESSORS
468inline
470{
471 return 0 != d_collector_p
472 && d_collector_p->metricId().category()->enabled();
473}
474
475} // close package namespace
476
477
478#endif
479
480// ----------------------------------------------------------------------------
481// Copyright 2015 Bloomberg Finance L.P.
482//
483// Licensed under the Apache License, Version 2.0 (the "License");
484// you may not use this file except in compliance with the License.
485// You may obtain a copy of the License at
486//
487// http://www.apache.org/licenses/LICENSE-2.0
488//
489// Unless required by applicable law or agreed to in writing, software
490// distributed under the License is distributed on an "AS IS" BASIS,
491// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
492// See the License for the specific language governing permissions and
493// limitations under the License.
494// ----------------------------- END-OF-FILE ----------------------------------
495
496/** @} */
497/** @} */
498/** @} */
bool enabled() const
Definition balm_category.h:340
Definition balm_collector.h:152
const MetricId & metricId() const
Definition balm_collector.h:308
void update(double value)
Definition balm_collector.h:271
Definition balm_metricid.h:162
const Category * category() const
Definition balm_metricid.h:319
Definition balm_metric.h:250
static Collector * lookupCollector(const char *category, const char *name, MetricsManager *manager=0)
Definition balm_metric.h:456
Definition balm_metricsmanager.h:490
Definition balm_stopwatchscopedguard.h:232
~StopwatchScopedGuard()
Definition balm_stopwatchscopedguard.h:460
Units
Definition balm_stopwatchscopedguard.h:236
@ k_MICROSECONDS
Definition balm_stopwatchscopedguard.h:240
@ BAEM_NANOSECONDS
Definition balm_stopwatchscopedguard.h:244
@ BAEM_MICROSECONDS
Definition balm_stopwatchscopedguard.h:245
@ MICROSECONDS
Definition balm_stopwatchscopedguard.h:249
@ BAEM_MILLISECONDS
Definition balm_stopwatchscopedguard.h:246
@ SECONDS
Definition balm_stopwatchscopedguard.h:251
@ BAEM_SECONDS
Definition balm_stopwatchscopedguard.h:247
@ NANOSECONDS
Definition balm_stopwatchscopedguard.h:248
@ k_SECONDS
Definition balm_stopwatchscopedguard.h:242
@ k_MILLISECONDS
Definition balm_stopwatchscopedguard.h:241
@ k_NANOSECONDS
Definition balm_stopwatchscopedguard.h:239
@ MILLISECONDS
Definition balm_stopwatchscopedguard.h:250
bool isActive() const
Definition balm_stopwatchscopedguard.h:469
Definition bsls_stopwatch.h:149
void start(bool collectCpuTimes=false)
Definition bsls_stopwatch.h:348
double elapsedTime() const
Definition bsls_stopwatch.h:427
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balm_bdlmmetricsadapter.h:141