BDE 4.39.x Production Release
Loading...
Searching...
No Matches
balm.h
Go to the documentation of this file.
1
/// @file balm.h
2
///
3
///
4
/// @defgroup balm Package balm
5
/// @brief Basic Application Library Metrics (balm)
6
/// @addtogroup bal
7
/// @{
8
/// @addtogroup balm
9
/// @{
10
/// * <a href="#balm-purpose"> Purpose</a>
11
/// * <a href="#balm-mnemonic"> Mnemonic </a>
12
/// * <a href="#balm-description"> Description </a>
13
/// * <a href="#balm-hierarchical-synopsis"> Hierarchical Synopsis </a>
14
/// * <a href="#balm-component-synopsis"> Component Synopsis </a>
15
/// * <a href="#balm-getting-started"> Getting Started </a>
16
/// * <a href="#balm-features-overview"> Features Overview </a>
17
/// * <a href="#balm-multi-threading"> Multi-Threading </a>
18
/// * <a href="#balm-collecting-metrics"> Collecting Metrics </a>
19
/// * <a href="#balm-choosing-between-ref-balm_metric-and-ref-balm_integermetric"> Choosing Between @ref balm_metric and @ref balm_integermetric </a>
20
/// * <a href="#balm-choosing-between-metric-collection-macros-and-metric-collection-classes"> Choosing Between Metric Collection Macros and Metric Collection Classes </a>
21
/// * <a href="#balm-creating-a-user-defined-collection-mechanism"> Creating a User Defined Collection Mechanism </a>
22
/// * <a href="#balm-publishing-metrics"> Publishing Metrics </a>
23
/// * <a href="#balm-periodically-publishing-metrics"> Periodically Publishing Metrics </a>
24
/// * <a href="#balm-disabling-metric-categories"> Disabling Metric Categories </a>
25
///
26
/// # Purpose {#balm-purpose}
27
/// Provide thread-safe collection and publishing of metrics.
28
///
29
/// # Mnemonic {#balm-mnemonic}
30
/// Basic Application Library Metrics (balm)
31
///
32
/// # Description {#balm-description}
33
/// The 'balm' package provides facilities for recording and
34
/// publishing metric data.
35
///
36
/// Bloomberg internal software should also consider the GUTS telemetry API, which
37
/// is integrated into Bloomberg infrastructure.
38
///
39
/// A "metric", in the context of this package, is a measured event. This package
40
/// does *not* define what constitutes an event or what the associated measurement
41
/// represents. For example, a metric could record the elapsed time of a function
42
/// call (in which case the event is the function call, and the measured value is
43
/// the elapsed time), or a metric could record the number of requests received by
44
/// a service (in which case the event is the reception of a request, and the
45
/// measured value is 1).
46
///
47
/// This package provides components for collecting and aggregating measurement
48
/// values (see @ref balm_metric and @ref balm_metrics ). Those aggregated metric
49
/// measurements are described by a metric record (see @ref balm_metricrecord ), which
50
/// contains the identifier for the recorded metric, the number of times the event
51
/// occurred, as well as the minimum, maximum, and total of the measured values.
52
/// This package provides a protocol for publishing metric records (see
53
/// @ref balm_publisher ) and an implementation of that protocol for publishing
54
/// records to a stream (see 'balm_streampublisher). Finally this package
55
/// provides a @ref balm_metricsmanager component to coordinate the collection and
56
/// publication of metrics.
57
///
58
/// ## Hierarchical Synopsis {#balm-hierarchical-synopsis}
59
///
60
/// The 'balm' package currently has 22 components having 13 levels of physical
61
/// dependency. The list below shows the hierarchical ordering of the components.
62
/// The order of components within each level is not architecturally significant,
63
/// just alphabetical.
64
/// @code
65
/// 13. balm_configurationutil
66
///
67
/// 12. balm_metrics
68
///
69
/// 11. balm_stopwatchscopedguard
70
///
71
/// 10. balm_bdlmmetricsadapter
72
/// balm_integermetric
73
/// balm_metric
74
///
75
/// 9. balm_defaultmetricsmanager
76
/// balm_publicationscheduler
77
///
78
/// 8. balm_metricsmanager
79
/// balm_streampublisher
80
///
81
/// 7. balm_collectorrepository
82
/// balm_publisher
83
///
84
/// 6. balm_collector
85
/// balm_integercollector
86
/// balm_metricsample
87
///
88
/// 5. balm_metricrecord
89
/// balm_metricregistry
90
///
91
/// 4. balm_metricid
92
///
93
/// 3. balm_metricdescription
94
///
95
/// 2. balm_metricformat
96
///
97
/// 1. balm_category
98
/// balm_publicationtype
99
/// @endcode
100
///
101
/// ## Component Synopsis {#balm-component-synopsis}
102
///
103
/// @ref balm_bdlmmetricsadapter :
104
/// Provide a concrete instance of the `bdlm` metrics adapter.
105
///
106
/// @ref balm_category :
107
/// Provide a representation of a metric category.
108
///
109
/// @ref balm_collector :
110
/// Provide a container for collecting and aggregating metric values.
111
///
112
/// @ref balm_collectorrepository :
113
/// Provide a repository for collectors.
114
///
115
/// @ref balm_configurationutil :
116
/// Provide a namespace for metrics configuration utilities.
117
///
118
/// @ref balm_defaultmetricsmanager :
119
/// Provide for a default instance of the metrics manager.
120
///
121
/// @ref balm_integercollector :
122
/// Provide a container for collecting integral metric values.
123
///
124
/// @ref balm_integermetric :
125
/// Provide helper classes for recording int metric values.
126
///
127
/// @ref balm_metric :
128
/// Provide helper classes for recording metric values.
129
///
130
/// @ref balm_metricdescription :
131
/// Provide a description for a metric.
132
///
133
/// @ref balm_metricformat :
134
/// Provide a formatting specification for a metric.
135
///
136
/// @ref balm_metricid :
137
/// Provide an identifier for a metric.
138
///
139
/// @ref balm_metricrecord :
140
/// Provide an aggregated record of the value of a metric.
141
///
142
/// @ref balm_metricregistry :
143
/// Provide a registry for metrics.
144
///
145
/// @ref balm_metrics :
146
/// Provide a suite of operations for recording metric values.
147
///
148
/// @ref balm_metricsample :
149
/// Provide a container for a sample of collected metric records.
150
///
151
/// @ref balm_metricsmanager :
152
/// Provide a manager for recording and publishing metric data.
153
///
154
/// @ref balm_publicationscheduler :
155
/// Provide a scheduler for publishing metrics.
156
///
157
/// @ref balm_publicationtype :
158
/// Provide an enumeration of aggregate types used to publish metrics.
159
///
160
/// @ref balm_publisher :
161
/// Provide a protocol to publish recorded metric values.
162
///
163
/// @ref balm_stopwatchscopedguard :
164
/// Provide a scoped guard for recording elapsed time.
165
///
166
/// @ref balm_streampublisher :
167
/// Provide a `balm::Publisher` implementation that writes to a stream.
168
///
169
/// ## Getting Started {#balm-getting-started}
170
///
171
/// The following section presents a simple example of collecting metrics. We
172
/// create a trivial application that reads lines of text from standard input and
173
/// counts the number of letters, words, and unique words in each line. The
174
/// function 'processLine()' processes each line of text and records metrics for
175
/// the number of times 'processLine()' has been called, the elapsed time for the
176
/// calls to 'processLine()', the total character count, and the total word count.
177
///
178
/// Before we can collect metrics we must first create a 'balm_MetricsManager'
179
/// object to manage their collection (and publication). We use the
180
/// 'balm_DefaultMetricsManager', which is a singleton instance of the
181
/// 'balm_MetricsManager' class. The default metrics manager is used by the
182
/// collection macros that we will use to collect metrics (see @ref balm_metrics ).
183
/// Note that the default metrics manager is intended to be created and destroyed
184
/// by the *owner* of 'main'. A default metrics manager instance should be
185
/// created during the initialization of an application (while the task has a
186
/// single thread) and destroyed just prior to termination (when there is,
187
/// similarly, a single thread).
188
/// @code
189
/// int main(int argc, const char *argv[])
190
/// {
191
/// @endcode
192
/// We create a 'balm_DefaultMetricsManagerScopedGuard', which manages the
193
/// lifetime of the default metrics manager (singleton) instance. At
194
/// construction, we provide the scoped guard an output stream ('stdout') to which
195
/// the @ref balm_publisher (created by the default metrics manager) will publish
196
/// metrics.
197
/// @code
198
/// balm_DefaultMetricsManagerScopedGuard managerGuard(bdl::cout);
199
/// @endcode
200
/// We create a 'balm_PublicationScheduler' to periodically publish the metrics we
201
/// have collected. A 'balm_PublicationScheduler' invokes 'publish()' on the
202
/// supplied 'balm_MetricsManager' object according to the provided schedule.
203
/// @code
204
/// bcep_TimerEventScheduler eventScheduler;
205
/// balm_PublicationScheduler publicationScheduler(
206
/// balm_DefaultMetricsManager::instance(),
207
/// &eventScheduler);
208
/// @endcode
209
/// To begin periodically publishing metrics we 'start' the event scheduler
210
/// supplied to the 'balm_PublicationScheduler', and then set a simple schedule to
211
/// publish all collected metrics every 30 seconds.
212
/// @code
213
/// eventScheduler.start();
214
/// publicationScheduler.setDefaultSchedule(bsls::TimeInterval(30, 0));
215
/// @endcode
216
/// Finally we have our main "application" loop, which reads lines of text from
217
/// the standard input (until "exit" is provided as input) and calls
218
/// 'processLine()' for each line of input.
219
/// @code
220
/// while (true) {
221
/// enum { BUFFER_SIZE = 1024 };
222
/// char buffer[BUFFER_SIZE];
223
/// if (!bdl::cin.getline(buffer, BUFFER_SIZE)) {
224
/// break;
225
/// }
226
/// if (0 == bdl::strcmp(buffer, "exit")) {
227
/// break;
228
/// }
229
/// processLine(buffer);
230
/// }
231
/// @endcode
232
/// At the end of this lexical scope 'managerGuard' is destroyed, releasing the
233
/// default 'balm_MetricsManager' instance.
234
/// @code
235
/// }
236
/// @endcode
237
/// Next we define the 'processLine()' function. The 'processLine()' function
238
/// "processes" a line of text, and collects several metrics related to the
239
/// function invocation.
240
/// @code
241
/// void processLine(const bdl::string& line)
242
/// // Process the specified 'line' of text and write to standard output the
243
/// // number of characters, words, and unique words in 'line'.
244
/// {
245
/// @endcode
246
/// Increment the count of the number of calls to 'processLine()' and use the
247
/// 'BALM_METRICS_TIME_BLOCK' macro (see @ref balm_metrics ) to collect the elapsed
248
/// time of this function call. Note that all the metrics recorded by this
249
/// function belong to the (arbitrarily chosen) category "Example".
250
/// @code
251
/// BALM_METRICS_INCREMENT("Example", "processLineCount");
252
/// BALM_METRICS_TIME_BLOCK("Example",
253
/// "processLineElapsedTime",
254
/// balm_StopwatchScopedGuard::BALM_SECONDS);
255
///
256
/// int wordCount = 0;
257
/// bdl::set<bdl::string> words;
258
///
259
/// bdl::string word;
260
/// bdl::istringstream istream(line);
261
/// while (istream >> word) {
262
/// words.insert(word);
263
/// ++wordCount;
264
/// }
265
///
266
/// bdl::cout << "Characters: count: " << line.size()
267
/// << "\tWord count: " << wordCount
268
/// << "\tUnique word count: " << words.size() << bdl::endl;
269
///
270
/// @endcode
271
/// Once we've "processed" the 'line', update the character count and word count
272
/// metrics.
273
/// @code
274
/// BALM_METRICS_UPDATE("Example", "characterCount", line.size());
275
/// BALM_METRICS_UPDATE("Example", "wordCount", wordCount);
276
/// }
277
/// @endcode
278
/// We've now created our example application. A typical session with this
279
/// application might look like (note that '>' indicates user input):
280
/// @code
281
/// >this contains 4 words
282
/// Characters: count: 21 Word count: 4 Unique word count: 4
283
/// >this sentence contains 5 words
284
/// Characters: count: 30 Word count: 5 Unique word count: 5
285
/// @endcode
286
/// Every 30 seconds metrics will be reported to standard output. A typical
287
/// publication of metrics would look like:
288
/// @code
289
/// 17FEB2009_15:29:20.792+0000 4 Records
290
/// Elapsed Time: 30.0092s
291
/// Example.processLineCount [ count = 2, total = 2, min = 1, max = 1 ]
292
/// Example.processLineElapsedTime [ count = 2, total = 0.0007656,
293
/// min = 0.00022736, max = 0.00053824 ]
294
/// Example.characterCount [ count = 2, total = 51, min = 21, max = 30 ]
295
/// Example.wordCount [ count = 2, total = 9, min = 4, max = 5 ]
296
/// @endcode
297
///
298
/// ## Features Overview {#balm-features-overview}
299
///
300
/// This section provides a brief summary of the features of the 'balm'
301
/// package - details can be found in the indicated components and later in this
302
/// document.
303
///
304
/// * A protocol to provide pluggable publishing behavior. Users can define and
305
/// register publishers with the metrics manager, which in turn defines the
306
/// behavior of the "publish" operation (see @ref balm_publisher )
307
///
308
/// * A default (singleton) metrics manager instance (see
309
/// @ref balm_defaultmetricsmanager )
310
///
311
/// * Simple macros for recording metrics to the default (singleton) metrics
312
/// manager instance (see @ref balm_metrics )
313
///
314
/// * Simple types for recording metrics (see @ref balm_metric and
315
/// @ref balm_integermetric )
316
///
317
/// * A guard helper class for recording the elapsed time of a block of code to a
318
/// metric (see @ref balm_stopwatchscopedguard )
319
///
320
/// * The ability to enable and disable the collection and publication of
321
/// categories of metrics (see @ref balm_metricsmanager and @ref balm_category )
322
///
323
/// * A scheduling mechanism for configuring the periodic publication of metrics
324
/// (see @ref balm_publicationscheduler )
325
///
326
/// ## Multi-Threading {#balm-multi-threading}
327
///
328
/// The components provided by the 'balm' package were designed for use in
329
/// multi-threaded applications. Metrics can be safely collected and published
330
/// simultaneously from multiple threads. Nevertheless, not every individual
331
/// component in the 'balm' package is thread-safe. See the individual component
332
/// documentation for more information.
333
///
334
/// ## Collecting Metrics {#balm-collecting-metrics}
335
///
336
/// The 'balm' package defines several ways to collect metrics, as well as
337
/// allowing users to define their own collection mechanisms.
338
///
339
/// ### Choosing Between @ref balm_metric and @ref balm_integermetric {#balm-choosing-between-ref-balm_metric-and-ref-balm_integermetric}
340
///
341
/// The @ref balm_metric and @ref balm_integermetric components both define macros and
342
/// helper classes for recording metrics. The mechanisms in @ref balm_integermetric
343
/// are slightly more efficient for collecting integral metric values, but are
344
/// otherwise identical.
345
///
346
/// ### Choosing Between Metric Collection Macros and Metric Collection Classes {#balm-choosing-between-metric-collection-macros-and-metric-collection-classes}
347
///
348
/// The macros and classes defined by the @ref balm_metric , @ref balm_integermetric and
349
/// @ref balm_metrics components provide the same basic functionality. Clients may
350
/// find the 'balm_Metric' or 'balm_IntegerMetric' classes better suited to
351
/// collecting metrics associated with a particular instance of a stateful object,
352
/// while the 'BALM_METRICS_*' macros are better suited to collecting metrics
353
/// associated with a particular code path (rather than an object instance). In
354
/// most instances, however, choosing between the two is a matter of taste.
355
///
356
/// ### Creating a User Defined Collection Mechanism {#balm-creating-a-user-defined-collection-mechanism}
357
///
358
/// The 'balm' package allows users to define their own metric collection
359
/// mechanisms by registering a callback with a 'balm_MetricsManager' object.
360
/// User defined callbacks must match the
361
/// 'balm_MetricsManager::MetricsCollectionCallback' function signature and
362
/// collect metrics for a *single* category. Every time 'publish' is invoked for
363
/// a category, the metrics manager will invoke the registered collection
364
/// callbacks for that category, and publish the collected metrics. See
365
/// @ref balm_metricsmanager for more information.
366
///
367
/// ## Publishing Metrics {#balm-publishing-metrics}
368
///
369
/// The @ref balm_publisher component defines a protocol for publishing metric
370
/// records. Users can register publisher objects with a metrics manager.
371
/// Invoking 'publish()' on a metrics manager will collect metrics for the set of
372
/// categories supplied with the function call, and then publish the metrics for
373
/// each supplied category to publishers registered for that category.
374
///
375
/// The 'balm_StreamPublisher' class implements the 'balm_Publisher' protocol to
376
/// provide a default publisher for publishing metrics to a stream.
377
///
378
/// ## Periodically Publishing Metrics {#balm-periodically-publishing-metrics}
379
///
380
/// Users can schedule the periodic publication of metrics using the
381
/// @ref balm_publicationscheduler component. In the example presented above, under
382
/// "Getting Started", a 'balm_PublicationScheduler' object was configured to
383
/// publish all categories of metrics metrics every 30 seconds.
384
///
385
/// At construction, a 'balm_PublicationScheduler' object is provided the
386
/// addresses of a 'balm_MetricsManager' and a 'bcep_TimerEventScheduler'. Users
387
/// can call 'scheduleCategory()' to schedule an individual metric category to be
388
/// published repeatedly at a given interval, or call 'setDefaultSchedule()' to
389
/// schedule the publication of any category not given an individual schedule. At
390
/// the end of a scheduled time interval, the publication scheduler invokes the
391
/// metrics manager's 'publish()' operation with the set of categories to publish.
392
/// Note that, the publication scheduler will combine categories that occur at the
393
/// same frequency into a single invocation of the metrics manager's 'publish'
394
/// operation.
395
///
396
/// ## Disabling Metric Categories {#balm-disabling-metric-categories}
397
///
398
/// Users can disable (and re-enable) a category of metrics by calling
399
/// 'balm_MetricsManager::setCategoryEnabled' method. A disabled category will
400
/// not be published by the metrics manager. In addition, the @ref balm_metric ,
401
/// @ref balm_integermetric , @ref balm_metrics , and @ref balm_stopwatchscopedguard
402
/// components will not collect metrics for disabled categories (minimizing the
403
/// performance cost of collecting metric for disabled categories). Note that
404
/// when 'balm_MetricsManager::publish()' is called on a disabled category, the
405
/// metrics manager *will* invoke any user defined collection callbacks registered
406
/// for the disable category, but *will* *not* publish the collected metrics.
407
/// Users defining their own metrics collection mechanism (using a
408
/// 'balm_MetricsManager::MetricsCollectionCallback') must (manually) test whether
409
/// a category is disabled if they wish to avoid collecting metrics for a disabled
410
/// category.
411
///
412
/// @}
413
/** @} */
doxygen_input
bde
groups
bal
balm
doc
balm.h
Generated by
1.9.8