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