BDE 4.39.x Production Release
Loading...
Searching...
No Matches
ball_loggermanager.h
Go to the documentation of this file.
1/// @file ball_loggermanager.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_loggermanager.h -*-C++-*-
8#ifndef INCLUDED_BALL_LOGGERMANAGER
9#define INCLUDED_BALL_LOGGERMANAGER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_loggermanager ball_loggermanager
15/// @brief Provide a manager of core logging functionality.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_loggermanager
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_loggermanager-purpose"> Purpose</a>
25/// * <a href="#ball_loggermanager-classes"> Classes </a>
26/// * <a href="#ball_loggermanager-description"> Description </a>
27/// * <a href="#ball_loggermanager-general-features-and-behavior"> General Features and Behavior </a>
28/// * <a href="#ball_loggermanager-logger-manager-singleton-initialization"> Logger Manager Singleton Initialization </a>
29/// * <a href="#ball_loggermanager-deprecation-notice"> Deprecation Notice </a>
30/// * <a href="#ball_loggermanager-categories-severities-and-threshold-levels"> Categories, Severities, and Threshold Levels </a>
31/// * <a href="#ball_loggermanager-terminology-factory-default-thresholds"> Terminology: "Factory Default" Thresholds </a>
32/// * <a href="#ball_loggermanager-category-creation-management-and-threshold-levels"> Category Creation, Management, and Threshold Levels </a>
33/// * <a href="#ball_loggermanager-log-record-contents"> Log Record Contents </a>
34/// * <a href="#ball_loggermanager-multi-threaded-usage"> Multi-Threaded Usage </a>
35/// * <a href="#ball_loggermanager-bsls-log-logging-redirection"> bsls::Log Logging Redirection </a>
36/// * <a href="#ball_loggermanager-usage"> Usage </a>
37/// * <a href="#ball_loggermanager-example-1-initialization-case-1"> Example 1: Initialization Case 1 </a>
38/// * <a href="#ball_loggermanager-example-2-initialization-case-2"> Example 2: Initialization Case 2 </a>
39/// * <a href="#ball_loggermanager-example-3-efficient-logging-of-ostream-able-objects"> Example 3: Efficient Logging of ostream-able Objects </a>
40/// * <a href="#ball_loggermanager-example-4-logging-using-a-ball-logger"> Example 4: Logging using a ball::Logger </a>
41///
42/// # Purpose {#ball_loggermanager-purpose}
43/// Provide a manager of core logging functionality.
44///
45/// # Classes {#ball_loggermanager-classes}
46///
47/// - ball::Logger: log record store and publication manager
48/// - ball::LoggerManager: logger factory and category administrator
49/// - ball::LoggerManagerScopedGuard: scoped guard for `LoggerManager` singleton
50///
51/// @see ball_record, ball_recordattributes, ball_observer, ball_context,
52/// ball_loggermanagerdefaults, ball_loggermanagerconfiguration,
53/// ball_severity, ball_transmission, ball_log
54///
55/// # Description {#ball_loggermanager-description}
56/// This component provides the core of the `ball` logging toolkit:
57/// the logger class itself, `ball::Logger`, that manages log record storage
58/// and publication control; the logger manager class, `ball::LoggerManager`,
59/// typically instantiated as a singleton, that is both a factory for loggers
60/// and a category manager; and the logger manager scoped guard,
61/// `ball::LoggerManagerScopedGuard`, that provides a convenient way to
62/// initialize and manage lifetime of the logger manager singleton object.
63///
64/// ## General Features and Behavior {#ball_loggermanager-general-features-and-behavior}
65///
66///
67/// The `ball` logging toolkit is very flexible. A user can log messages with
68/// very little effort, and with only a superficial understanding of logger
69/// operation, in which case the logger will exhibit its "default behavior".
70/// The user can also elect to customize many aspects of logging, such as
71/// storage and publication behavior, both at start-up and dynamically during
72/// program execution. Naturally, to exercise such control, the user must
73/// become more familiar with `ball` logger operation; the user can choose more
74/// convenience or more versatility, with a reasonably fine granularity.
75///
76/// Log records incorporate both fixed (logger-defined) and optional
77/// (user-defined) fields, affording yet more flexibility (see "Log Record
78/// Contents" below). The logger directly populates certain of the required
79/// fields, and indirectly manages population of any optional fields by invoking
80/// a client-supplied callback function that sets the optional values.
81///
82/// Clients obtain one or more loggers from the logger manager, although at most
83/// one logger may be "active" in any one thread; a request to log a message is
84/// directed to the active logger in that thread. Each logger both stores and
85/// publishes appropriate log records.
86///
87/// All loggers share a single internal broadcast observer to which log records
88/// are transmitted when they are published (see the component-level
89/// documentation of @ref ball_observer for more information on observers).
90///
91/// A logger can achieve high performance through the use of an in-memory record
92/// buffer for storing the records logged by a program. Each logger is
93/// constructed with a record manager that is an instance of a concrete class
94/// derived from `ball::RecordBuffer`. The singleton logger manager supplies a
95/// "default" record manager to the default logger; loggers allocated by the
96/// logger manager's `allocateLogger` method use a record manager supplied by
97/// the client. The default log record buffer is of user-configurable static
98/// size and is circular (see the @ref ball_circularrecordbuffer component for
99/// details), whereby continuous logging (without publication of logged records)
100/// can result in older records being overwritten by newer ones. A circular
101/// buffer provides an efficient "trace-back" strategy, wherein only log records
102/// proximate to a user-specified logging event (see below) are published. Such
103/// a circular buffer may not be appropriate for all situations; the user can
104/// change the behavior of the default logger by adjusting the logging threshold
105/// levels (see below) or can install a logger that uses a different kind of
106/// record buffer.
107///
108/// ## Logger Manager Singleton Initialization {#ball_loggermanager-logger-manager-singleton-initialization}
109///
110///
111/// The recommended way to initialize the logger manager singleton is to create
112/// a `ball::LoggerManagerScopedGuard` object in `main` *before* creating any
113/// threads. The logger manager scoped guard constructor takes a configuration
114/// object (an instance of `ball::LoggerManagerConfiguration`), and an optional
115/// allocator. The logger manager singleton is created as a side-effect of
116/// creating the scoped guard object. When the guard object goes out of scope
117/// (i.e., on program exit), the logger manager singleton is automatically
118/// destroyed.
119///
120/// The `ball::LoggerManagerConfiguration` object is used to supply a set of
121/// user-defined "default" values and other options. However, to obtain the
122/// "default" logging behavior, it is sufficient to instantiate a default
123/// `ball::LoggerManagerConfiguration` object and pass that to the constructor
124/// of the scoped guard along with an observer. (See {Usage} below.)
125///
126/// As an alternative to using the scoped guard, the `initSingleton` method that
127/// takes the same arguments as the scoped guard may be used to initialize the
128/// singleton. However, in this case the `shutDownSingleton` method must be
129/// explicitly called to destroy the logger manager singleton on program exit.
130/// Unless `shutDownSingleton` is called, the singleton will not be destroyed
131/// and resources used by the singleton will leak.
132///
133/// Note that the logger manager singleton *can* be reinitialized after it has
134/// been destroyed. However, such practice should generally be restricted to
135/// test drivers and very specialized use cases. Clients should generally avoid
136/// initializing and destroying the singleton more than once in a program unless
137/// they know what they are doing.
138///
139/// ## Deprecation Notice {#ball_loggermanager-deprecation-notice}
140///
141///
142/// Direct use of any of the `ball::LoggerManager` or
143/// `ball::LoggerManagerScopedGuard` methods that take raw pointers to observers
144/// is *deprecated*. These methods will be eliminated in a future release.
145///
146/// The `ball::LoggerManagerCategoryIter` and `ball::LoggerManagerCategoryManip`
147/// classes are *deprecated*. Clients of `ball::LoggerManager` should use the
148/// `visitCategories` accessor (the replacement for `LoggerManagerCategoryIter`)
149/// or `visitCategories` manipulator (replacing `LoggerManagerCategoryManip`)
150/// instead.
151///
152/// ## Categories, Severities, and Threshold Levels {#ball_loggermanager-categories-severities-and-threshold-levels}
153///
154///
155/// **NOTE**: Category management functionality, including category creation,
156/// lookup, threshold level administration, and hierarchical category support,
157/// is implemented by `ball::CategoryManager`. `ball::LoggerManager` provides
158/// forwarding methods for convenient access to these functions. For
159/// comprehensive documentation on category management, including detailed
160/// explanations of threshold mechanisms, hierarchical categories, callbacks,
161/// and usage examples, see the @ref ball_categorymanager component documentation.
162///
163/// The logger supports the notions of "severity level" and "category"; every
164/// record is logged at some severity level and to some category. Categories
165/// are user-defined (except for the "default category"), and have unique names.
166/// Severity levels are integers in the range `[0 .. 255]`, and are most
167/// typically chosen from among the enumeration in the @ref ball_severity
168/// component, although use of the `enum` is optional. The severity level and
169/// the category name are each among the fixed fields of the record being logged
170/// (see "Log Record Contents" below).
171///
172/// From the logger's perspective, all categories are peers; there is no special
173/// significance to any sequence of characters in a category name. The user may
174/// impose a hierarchical *meaning* to category names, and the logger manager
175/// facilitates a certain degree of hierarchical *behavior* via several callback
176/// functors provided within this component (see below, and also the
177/// @ref ball_loggerfunctorpayloads component). However, such hierarchy is not
178/// fundamental to categories, nor to the behavior described in this section.
179/// Similarly, there is no a priori significance to severity levels except that
180/// they are ordered and may be compared for inequality, although the enumerator
181/// names in the `ball::Severity::Level` enumeration (e.g., `DEBUG`, `WARN`,
182/// `ERROR`, etc.) suggest the intended "standard" meanings.
183///
184/// Every category has associated with it four "severity threshold levels" that
185/// may be set explicitly by the user on category creation/registration (via the
186/// `addCategory` method) or else will default to specific values via one of
187/// several mechanisms described below (invoked by the one-argument
188/// `setCategory` method). Category threshold levels may also be changed during
189/// program execution via the five-argument `setCategory` method.
190///
191/// When the user logs a record to a given category and at a given severity (via
192/// the `ball::Logger` `logMessage` method or via the logging macros -- see the
193/// `ball_log` component), the logger manager uses the specified severity and
194/// the category's registered severity threshold levels to govern the logger's
195/// behavior; depending on the thresholds, the message may be recorded to an
196/// in-memory buffer, published to an external observer, or ignored. In
197/// addition, if thresholds are set appropriately, the entire contents of the
198/// in-memory buffer of one or more loggers may be published to external
199/// observers. Clients of the logger can use, and dynamically administer, the
200/// category threshold levels to enhance run-time performance and/or to reduce
201/// message volume while still capturing all critical log messages.
202///
203/// The names and exact meanings of the four severity threshold levels are as
204/// follows:
205///
206/// * **Record**
207/// > If the severity level of the record is at least as severe as the Record
208/// > threshold level of the associated category, then the record will be
209/// > stored by the logger in its log record buffer (i.e., it will be
210/// > recorded).
211///
212/// * **Pass**
213/// > If the severity of the record is at least as severe as the Pass
214/// > threshold level of the associated category, then the record will be
215/// > immediately published by the logger (i.e., it will be transmitted to
216/// > the logger's downstream recipient -- the observer).
217///
218/// * **Trigger**
219/// > If the severity of the record is at least as severe as the Trigger
220/// > threshold level of the associated category, then the record will cause
221/// > immediate publication of that record and any records in the logger's
222/// > log record buffer (i.e., this record will trigger a general log record
223/// > dump).
224///
225/// * **Trigger-All**
226/// > If the severity of the record is at least as severe as the Trigger-All
227/// > threshold level of the associated category, then the record will cause
228/// > immediate publication of that record and all other log records stored
229/// > by *all* active loggers.
230///
231/// Note that more than one of the above actions can apply to a given log
232/// record, since the four threshold levels are independent of one another.
233/// Note also that *all* of these actions are governed by the threshold levels
234/// of the record being logged, and not by the threshold levels of any stored
235/// records that are published as a result of a Trigger or Trigger-All event.
236///
237/// ### Terminology: "Factory Default" Thresholds {#ball_loggermanager-terminology-factory-default-thresholds}
238///
239///
240/// The logger manager supplies "default values" for category threshold levels
241/// whenever a category is created without client-supplied values. These
242/// default values can come from any one of several possible sources, depending
243/// upon options that the user has elected; the system is flexible, but leads to
244/// a bit of confusion in terminology. This section explains the meaning of
245/// "factory default" values and introduces the various "default" threshold
246/// mechanisms.
247///
248/// The logger manager is a "factory" for loggers; we therefore define "factory
249/// defaults" to be the default values that the `ball::LoggerManager` singleton
250/// is aware of at construction. Depending on the values and options in the
251/// `ball::LoggerManagerConfiguration` object provided to the logger manager on
252/// construction, the factory defaults may be either implementation-defined or
253/// user-defined.
254///
255/// In either case, the user can *change* the default values during logger
256/// operation via the `setDefaultThresholdLevels` method. These threshold
257/// levels become the "default" values for new categories, but they do not
258/// affect the "factory defaults" that subsequently can be restored via the
259/// `resetDefaultThresholdLevels` method.
260///
261/// A third mechanism, the `ball::LoggerManager::DefaultThresholdLevelsCallback`
262/// functor, adds even more flexibility. If this callback is installed by the
263/// user at construction, or subsequently via the
264/// `setDefaultThresholdLevelsCallback` method, the callback is the source of
265/// all default thresholds, and the above mechanisms are not used. The next
266/// section covers category thresholds in more detail.
267///
268/// ### Category Creation, Management, and Threshold Levels {#ball_loggermanager-category-creation-management-and-threshold-levels}
269///
270///
271/// **NOTE**: The implementation of category management, including category
272/// creation, threshold level administration, callbacks, and hierarchical
273/// support, has been moved to `ball::CategoryManager`. The methods described
274/// in this section are now forwarding methods that delegate to the
275/// `ball::CategoryManager` owned by the logger manager. For detailed
276/// documentation on these mechanisms, see the @ref ball_categorymanager component.
277///
278/// When the logger manager singleton is created, a unique category known as the
279/// *Default* *Category* is created, and is given "factory-supplied" default
280/// threshold levels. The default values for the default category are each in
281/// the range `[0 .. 255]`, but are otherwise unspecified. The user can also
282/// specify default values explicitly when the logger manager singleton is
283/// constructed. This is accomplished by constructing a
284/// `ball::LoggerManagerDefaults` object, setting the desired values, and then
285/// setting that object as an attribute of the
286/// `ball::LoggerManagerConfiguration` argument to the
287/// `ball::LoggerManagerScopedGuard` constructor.
288///
289/// The default category is issued to the user via the return value of the
290/// `setCategory(const char *categoryName)` method whenever a new category
291/// cannot be created due to a capacity limitation on the category registry
292/// maintained by the logger manager. The method's normal behavior is to return
293/// the category having `categoryName`.
294///
295/// Categories that are added to the registry during logging through calls to
296/// the `setCategory(const char *)` method are given threshold levels by one of
297/// two means. The "default" mechanism (a slightly overloaded term in `ball`)
298/// is to use the same default thresholds as described above for the default
299/// category. The alternative is to specify a
300/// `ball::LoggerManager::DefaultThresholdLevelsCallback` functor, either when
301/// the logger manager singleton is initialized or else afterwards via the
302/// `setDefaultThresholdLevelsCallback` method. This functor, if provided, is
303/// used by the logger manager to supply the four `int` threshold values; the
304/// functor may generate these values by any means that the user sees fit. See
305/// the @ref ball_loggerfunctorpayloads component for an example payload function
306/// for the functor.
307///
308/// The default threshold levels can be adjusted (`setDefaultThresholdLevels`)
309/// and reset to their original values (`resetDefaultThresholdLevels`). Note
310/// that if factory values are overridden at initialization, a reset will
311/// restore thresholds to the user-specified default values. In addition, there
312/// is a method to set the threshold levels of a given category to the current
313/// default threshold levels (`setCategoryThresholdsToCurrentDefaults`) or to
314/// the factory-supplied (or client-overridden) default values
315/// (`setCategoryThresholdsToFactoryDefaults`).
316///
317/// As a final note regarding categories, a client can optionally supply to the
318/// logger manager on construction a
319/// `ball::LoggerManager::CategoryNameFilterCallback` functor (via the
320/// `ball::LoggerManagerConfiguration` object) to translate category names from
321/// an external to an internal representation. For example, a project may allow
322/// programmers to refer to categories using mixed-case within an application,
323/// but provide a `toLower` `CategoryNameFilterCallback` to map all external
324/// upper-case letters to lower-case internally. In this scenario, the
325/// (hypothetical) external category names "EQUITY.MARKET.NYSE" and
326/// "equity.market.nyse" would be mapped to the same category internally by the
327/// presumed `toLower` functor.
328///
329/// ## Log Record Contents {#ball_loggermanager-log-record-contents}
330///
331///
332/// Each log record contains a set of fixed fields and a set of optional,
333/// user-definable fields and attributes. The following table lists the fixed
334/// fields in each log record (see the component-level documentation of
335/// @ref ball_recordattributes for more information on the fixed fields of a log
336/// record):
337/// @code
338/// Field Name Type Description
339/// ----------- -------------- --------------------------------------
340/// timestamp bdlt::Datetime creation date and time
341/// process ID int process ID of creator
342/// thread ID int thread ID of creator
343/// filename string file where created (i.e., '__FILE__')
344/// line number int line number in file (i.e., '__LINE__')
345/// category string category name
346/// severity int severity of logged record
347/// message string log message text
348/// @endcode
349///
350/// The following table lists optional fields and attributes in each log record
351/// (see the component-level documentation of @ref ball_userfields and
352/// @ref ball_managedattribute for more information):
353/// @code
354/// Field Name Type Description
355/// ----------- -------------- -------------------------
356/// userFields ball::UserFields [!DEPRECATED!]
357/// attributes bsl::vector<ball::ManagedAttribute> user-managed log
358/// attributes
359/// @endcode
360///
361/// [**DEPRECATED**] If a `ball::LoggerManager::UserFieldsPopulatorCallback`
362/// functor is supplied by the client (see @ref ball_loggermanagerconfiguration ),
363/// thereafter, every logged record has its user-defined fields (indirectly)
364/// populated by an invocation of the `UserFieldsPopulatorCallback` functor.
365///
366/// The log record's attributes are populated by attribute collector functor(s)
367/// registered by the user.
368///
369/// ## Multi-Threaded Usage {#ball_loggermanager-multi-threaded-usage}
370///
371///
372/// The `ball` logging toolkit may be used in single-threaded and multi-threaded
373/// library code and applications with equal ease, and with virtually no
374/// difference in coding. In particular, the same use of the
375/// `ball::LoggerManagerScopedGuard` class to initialize the logger manager
376/// singleton is required in `main` in both cases, and individual calls to the
377/// `ball::Logger` instance method `logMessage` (and logging calls via the
378/// logging macros -- see `ball_log`) are identical, from the user's
379/// perspective. Category threshold administration is also identical in both
380/// cases.
381///
382/// Differences in logger usage, or, more precisely, additional options for the
383/// multi-threaded user, arise when the user wishes to allocate one or more
384/// loggers beyond the default logger that is owned by the singleton logger
385/// manager. If a user does *not* explicitly allocate a logger (via the logger
386/// manager instance method `allocateLogger`) and install that logger for a
387/// given thread (via the manager instance method `setLogger`), then all
388/// records from all threads in a program will be logged to the one default
389/// logger. However, since each thread of execution may have its own logger
390/// instance, multi-threaded users may choose to allocate and install multiple
391/// loggers. Note that each thread may have at most one logger, but a single
392/// logger may be used by any number of threads.
393///
394/// Multi-threaded users of logging may prefer to allocate and install one
395/// logger per thread in order to take advantage of the "trace-back" feature
396/// described above on a per-thread basis. In the event of an error condition
397/// as defined by the programmer, such a logging configuration provides a
398/// trace-back through the record buffer of the thread that caused the error,
399/// without any dilution from records from other threads. Conversely, if
400/// several threads are known to interact closely, it may be advantageous to
401/// have them share a common logger so that the trace-back log *does* include
402/// all relevant records.
403///
404/// ## bsls::Log Logging Redirection {#ball_loggermanager-bsls-log-logging-redirection}
405///
406///
407/// The `ball::LoggerManager` singleton, on construction, redirects `bsls::Log`
408/// messages to `ball`. Such messages use the logging category "BSLS.LOG".
409/// Upon its destruction, the logger manager singleton redirects `bsls::Log`
410/// messages back to the `bsls::Log` message handler that was in effect prior to
411/// the creation of the singleton (see `bsls_log`).
412///
413/// ## Usage {#ball_loggermanager-usage}
414///
415///
416/// This section illustrates instantiation of the logger manager singleton that
417/// is required in `main`, and also shows *direct* use of the logger and logger
418/// manager interfaces, much of which is actually *not* recommended. The most
419/// basic logger functionality has been wrapped in macros defined in the
420/// `ball_log` component. See the `ball` package-level documentation and the
421/// `ball_log` component documentation for recommended real-world usage
422/// examples.
423///
424/// ### Example 1: Initialization Case 1 {#ball_loggermanager-example-1-initialization-case-1}
425///
426///
427/// Clients that perform logging must first instantiate the singleton logger
428/// manager using the `ball::LoggerManagerScopedGuard` class. This example
429/// shows how to create a logger manager with the most basic "default behavior".
430/// Subsequent examples will show more customized behavior.
431///
432/// The following snippets of code illustrate the initialization sequence
433/// (typically performed near the top of `main`).
434///
435/// First, we create a `ball::LoggerManagerConfiguration` object,
436/// `configuration`, and set the logging "pass-through" level -- the level at
437/// which log records are published to registered observers -- to `WARN` (see
438/// {`Categories, Severities, and Threshold Levels`}):
439/// @code
440/// // myApp.cpp
441///
442/// int main()
443/// {
444/// ball::LoggerManagerConfiguration configuration;
445/// configuration.setDefaultThresholdLevelsIfValid(ball::Severity::e_WARN);
446/// @endcode
447/// Next, create a `ball::LoggerManagerScopedGuard` object whose constructor
448/// takes the configuration object just created. The guard will initialize the
449/// logger manager singleton on creation and destroy the singleton upon
450/// destruction. This guarantees that any resources used by the logger manager
451/// will be properly released when they are not needed:
452/// @code
453/// ball::LoggerManagerScopedGuard guard(configuration);
454/// @endcode
455/// Note that the application is now prepared to log messages using the `ball`
456/// logging subsystem, but until the application registers an observer, all log
457/// messages will be discarded.
458///
459/// Finally, we create a `ball::StreamObserver` object `observer` that will
460/// publish records to `stdout` and register it with the logger manager
461/// singleton. Note that observers must be registered by name; this example
462/// simply uses "default" for a name:
463/// @code
464/// bslma::Allocator *alloc = bslma::Default::globalAllocator(0);
465///
466/// bsl::shared_ptr<ball::StreamObserver> observer(
467/// new(*alloc) ball::StreamObserver(&bsl::cout),
468/// alloc);
469/// ball::LoggerManager::singleton().registerObserver(observer, "default");
470/// @endcode
471/// The application is now prepared to log messages using the `ball` logging
472/// subsystem:
473/// @code
474/// // ...
475///
476/// return 0;
477/// }
478/// @endcode
479/// Note that concrete observers that can be configured after their creation
480/// (e.g., as to whether log records are published in UTC or local time)
481/// generally can have their configuration adjusted at any time, either before
482/// or after being registered with a logger manager. For an example of such an
483/// observer, see @ref ball_asyncfileobserver .
484///
485/// ### Example 2: Initialization Case 2 {#ball_loggermanager-example-2-initialization-case-2}
486///
487///
488/// In this example, we demonstrate a more elaborate initial configuration for
489/// the logger manager. In particular, we create the singleton logger manager
490/// with a configuration that has a category name filter functor, a
491/// `DefaultThresholdLevelsCallback` functor, and user-chosen values for the
492/// "factory default" threshold levels.
493///
494/// First, we define three `static` functions that are employed by the two
495/// functors. The `toLower` function implements our category name filter. It
496/// is wrapped within a functor object and maps category names to lower-case:
497/// @code
498/// static
499/// void toLower(bsl::string *buffer, const char *s)
500/// {
501/// assert(buffer);
502/// assert(s);
503///
504/// buffer->clear();
505/// while (*s) {
506/// buffer->push_back(static_cast<char>(bsl::tolower(*s)));
507/// ++s;
508/// }
509/// buffer->push_back(0);
510/// }
511/// @endcode
512/// The following two functions provide the implementation for our
513/// `DefaultThresholdLevelsCallback` functor. The `inheritThresholdLevels`
514/// function is wrapped within a functor object; the `getDefaultThresholdLevels`
515/// function is a helper that does the hard work. We assume a hierarchical
516/// category naming scheme that uses `.` to delimit the constituents of names.
517/// For example, the three categories named "x", "x.y", and "x.y.z" are related
518/// in the sense that "x" is an ancestor of both "x.y" and "x.y.z", and "x.y" is
519/// an ancestor "x.y.z". Suppose that "x" is added to the registry first. If
520/// "x.y" is then added to the registry by calling `setCategory(const char *)`,
521/// it would "inherit" threshold level values from "x". Similarly, when "x.y.z"
522/// is added to the registry by calling the 1-argument `setCategory` method, it
523/// inherits threshold level values from "x.y" (i.e., a category inherits from
524/// its nearest ancestor that exists in the registry when it is added). Note
525/// that a category named "xx.y" (for example) is not related to either of "x",
526/// "x.y", or "x.y.z":
527/// @code
528/// /// Obtain appropriate threshold levels for the category having the
529/// /// specified `categoryName` by searching the registry of the specified
530/// /// `loggerManager`, and store the resulting values at the specified
531/// /// `recordLevel`, `passLevel`, `triggerLevel`, and `triggerAllLevel`
532/// /// addresses. A hierarchical category naming scheme is assumed that
533/// /// employs the specified `delimiter` to separate the components of
534/// /// category names. Return 0 on success, and a non-zero value
535/// /// otherwise. The behavior is undefined unless `recordLevel`,
536/// /// `passLevel`, `triggerLevel`, and `triggerAllLevel` are non-null, and
537/// /// `categoryName` is null-terminated.
538/// static
539/// int getDefaultThresholdLevels(int *recordLevel,
540/// int *passLevel,
541/// int *triggerLevel,
542/// int *triggerAllLevel,
543/// char delimiter,
544/// const ball::LoggerManager& loggerManager,
545/// const char *categoryName)
546/// {
547/// assert(recordLevel);
548/// assert(passLevel);
549/// assert(triggerLevel);
550/// assert(triggerAllLevel);
551/// assert(categoryName);
552///
553/// enum { SUCCESS = 0, FAILURE = -1 };
554///
555/// bsl::string buffer(categoryName);
556/// while (1) {
557/// const ball::Category *category =
558/// loggerManager.lookupCategory(buffer.c_str());
559/// if (0 != category) {
560/// *recordLevel = category->recordLevel();
561/// *passLevel = category->passLevel();
562/// *triggerLevel = category->triggerLevel();
563/// *triggerAllLevel = category->triggerAllLevel();
564/// return SUCCESS; // RETURN
565/// }
566///
567/// const char *newEnd = bsl::strrchr(buffer.c_str(), delimiter);
568/// if (0 == newEnd) {
569/// return FAILURE; // RETURN
570/// }
571/// buffer.resize(newEnd - buffer.data());
572/// }
573/// }
574///
575/// /// Obtain appropriate threshold levels for the category having the
576/// /// specified `categoryName`, and store the resulting values at the
577/// /// specified `recordLevel`, `passLevel`, `triggerLevel`, and
578/// /// `triggerAllLevel` addresses. The behavior is undefined unless
579/// /// `recordLevel`, `passLevel`, `triggerLevel`, and `triggerAllLevel`
580/// /// are non-null, and `categoryName` is null-terminated.
581/// static
582/// void inheritThresholdLevels(int *recordLevel,
583/// int *passLevel,
584/// int *triggerLevel,
585/// int *triggerAllLevel,
586/// const char *categoryName)
587/// {
588/// assert(recordLevel);
589/// assert(passLevel);
590/// assert(triggerLevel);
591/// assert(triggerAllLevel);
592/// assert(categoryName);
593///
594/// const ball::LoggerManager& manager = ball::LoggerManager::singleton();
595/// if (0 != getDefaultThresholdLevels(recordLevel,
596/// passLevel,
597/// triggerLevel,
598/// triggerAllLevel,
599/// '.',
600/// manager,
601/// categoryName)) {
602/// *recordLevel = manager.defaultRecordThresholdLevel();
603/// *passLevel = manager.defaultPassThresholdLevel();
604/// *triggerLevel = manager.defaultTriggerThresholdLevel();
605/// *triggerAllLevel = manager.defaultTriggerAllThresholdLevel();
606/// }
607/// }
608/// @endcode
609/// Then, we create the callback functors that will be supplied to the logger
610/// manager singleton initialization (as in "Example 1" above, we assume that
611/// the initialization sequence occurs somewhere near the top of `main`):
612/// @code
613/// // myApp2.cpp
614///
615/// int main() {
616/// // ...
617///
618/// ball::LoggerManager::CategoryNameFilterCallback nameFilter(&toLower);
619///
620/// ball::LoggerManager::DefaultThresholdLevelsCallback
621/// thresholdsCallback(&inheritThresholdLevels);
622/// @endcode
623/// Next, we define four values for our custom "factory default" thresholds.
624/// These values will be stored within the logger manager and will be available
625/// to all users whenever the "factory defaults" are needed, for the life of the
626/// logger manager. In this example, however, we will also be installing the
627/// `thresholdsCallback` defined above, so unless that functor is un-installed
628/// (by a call to `setDefaultThresholdLevelsCallback`), these four "factory
629/// defaults" will have no practical effect, since the callback mechanism "steps
630/// in front of" the default values:
631/// @code
632/// int recordLevel = 125;
633/// int passLevel = 100;
634/// int triggerLevel = 75;
635/// int triggerAllLevel = 50;
636/// @endcode
637/// Then, we can configure a `ball::LoggerManagerDefaults` object, `defaults`,
638/// with these four threshold values. `defaults` can then be used to configure
639/// the `ball::LoggerManagerConfiguration` object that will be passed to the
640/// `ball::LoggerManagerScopedGuard` constructor (below):
641/// @code
642/// ball::LoggerManagerDefaults defaults;
643/// defaults.setDefaultThresholdLevelsIfValid(recordLevel,
644/// passLevel,
645/// triggerLevel,
646/// triggerAllLevel);
647/// @endcode
648/// Next, we create and set the `ball::LoggerManagerConfiguration` object,
649/// `configuration`, that will describe our desired configuration:
650/// @code
651/// ball::LoggerManagerConfiguration configuration;
652/// configuration.setDefaultValues(defaults);
653/// configuration.setCategoryNameFilterCallback(nameFilter);
654/// configuration.setDefaultThresholdLevelsCallback(thresholdsCallback);
655/// @endcode
656/// Then, we instantiate the singleton logger manager, passing in the
657/// `configuration` that we have just created:
658/// @code
659/// ball::LoggerManagerScopedGuard guard(configuration);
660/// @endcode
661/// Note that the application is now prepared to log messages using the `ball`
662/// logging subsystem, but until the application registers an observer, all log
663/// messages will be discarded.
664///
665/// Now, we will demonstrate the functors and client-supplied default threshold
666/// overrides.
667///
668/// First, we obtain a reference to the singleton logger manager:
669/// @code
670/// ball::LoggerManager& manager = ball::LoggerManager::singleton();
671/// @endcode
672/// Then, we obtain a reference to the *Default* *Category* and `assert` that
673/// its threshold levels match the client-supplied values that override the
674/// "factory-supplied" default values:
675/// @code
676/// const ball::Category& defaultCategory = manager.defaultCategory();
677/// assert(125 == defaultCategory.recordLevel());
678/// assert(100 == defaultCategory.passLevel());
679/// assert( 75 == defaultCategory.triggerLevel());
680/// assert( 50 == defaultCategory.triggerAllLevel());
681/// @endcode
682/// Next, we add a category named "BloombergLP" (by calling `addCategory`).
683/// Note that threshold levels supplied with the category override all defaults
684/// (including thresholds set by the supplied callback). Also note that the
685/// logger manager invokes the supplied category name filter to map the category
686/// name to lower-case before the new category is added to the category
687/// registry. The name filter is also invoked by `lookupCategory` whenever a
688/// category is searched for (i.e., by name) in the registry:
689/// @code
690/// const ball::Category *blpCategory =
691/// manager.addCategory("BloombergLP", 128, 96, 64, 32);
692/// assert(blpCategory == manager.lookupCategory("BLOOMBERGLP"));
693/// assert( 0 == bsl::strcmp("bloomberglp", blpCategory->categoryName()));
694/// assert(128 == blpCategory->recordLevel());
695/// assert( 96 == blpCategory->passLevel());
696/// assert( 64 == blpCategory->triggerLevel());
697/// assert( 32 == blpCategory->triggerAllLevel());
698/// @endcode
699/// Then, we add a second category named "BloombergLP.bal.ball" (by calling
700/// `setCategory`) and `assert` that the threshold levels are "inherited" from
701/// category "BloombergLP":
702/// @code
703/// const ball::Category *ballCategory =
704/// manager.setCategory("BLOOMbergLP.bal.ball");
705///
706/// assert(ballCategory == manager.lookupCategory("bloomberglp.bal.ball"));
707/// assert( 0 == bsl::strcmp("bloomberglp.bal.ball",
708/// ballCategory->categoryName()));
709/// assert(128 == ballCategory->recordLevel());
710/// assert( 96 == ballCategory->passLevel());
711/// assert( 64 == ballCategory->triggerLevel());
712/// assert( 32 == ballCategory->triggerAllLevel());
713/// @endcode
714/// Now, we add a third category named "Other.equities", again by calling
715/// `setCategory`. This category has no ancestor currently in the registry, so
716/// its threshold levels match those of the *Default* *Category*:
717/// @code
718/// const ball::Category *equitiesCategory =
719/// manager.setCategory("Other.equities");
720/// assert(equitiesCategory == manager.lookupCategory("OTHER.EQUITIES"));
721/// assert( 0 == bsl::strcmp("other.equities",
722/// equitiesCategory->categoryName()));
723/// assert(125 == equitiesCategory->recordLevel());
724/// assert(100 == equitiesCategory->passLevel());
725/// assert( 75 == equitiesCategory->triggerLevel());
726/// assert( 50 == equitiesCategory->triggerAllLevel());
727/// @endcode
728/// Finally, we create a `ball::StreamObserver` object `observer` that will
729/// publish records to `stdout` and register it with the logger manager
730/// singleton. Note that observers must be registered by name; this example
731/// simply uses "default" for a name:
732/// @code
733/// bslma::Allocator *alloc = bslma::Default::globalAllocator(0);
734///
735/// bsl::shared_ptr<ball::StreamObserver> observer(
736/// new(*alloc) ball::StreamObserver(&bsl::cout),
737/// alloc);
738///
739/// manager.registerObserver(observer, "default");
740/// // ...
741///
742/// return 0;
743/// }
744/// @endcode
745///
746/// ### Example 3: Efficient Logging of ostream-able Objects {#ball_loggermanager-example-3-efficient-logging-of-ostream-able-objects}
747///
748///
749/// The following example demonstrates how instances of a class supporting
750/// streaming to `bsl::ostream` (via overloaded `operator<<`) can be logged. It
751/// also demonstrates how to use the `logMessage` method to log messages to a
752/// logger. Suppose we want to *efficiently* log instances of the following
753/// class:
754/// @code
755/// /// This (incomplete) class is a simple aggregate of a "heading" and
756/// /// "contents" pertaining to that heading. It serves to illustrate how
757/// /// to log the string representation of an object.
758/// class Information {
759///
760/// bsl::string d_heading;
761/// bsl::string d_contents;
762///
763/// public:
764/// Information(const char *heading, const char *contents);
765/// ~Information();
766/// const bsl::string& heading() const;
767/// const bsl::string& contents() const;
768/// };
769/// @endcode
770/// In addition, we define the following free operator for streaming instances
771/// of `Information` to an `bsl::ostream`:
772/// @code
773/// bsl::ostream& operator<<(bsl::ostream& stream,
774/// const Information& information)
775/// {
776/// stream << information.heading();
777/// stream << ": ";
778/// stream << information.contents() << bsl::endl;
779/// return stream;
780/// }
781/// @endcode
782/// The following function logs an `Information` object to the specified
783/// `logger`:
784/// @code
785/// void logInformation(ball::Logger *logger,
786/// const Information& information,
787/// ball::Severity::Level severity,
788/// const ball::Category& category,
789/// const char *fileName,
790/// int lineNumber)
791/// {
792/// @endcode
793/// First, obtain a record that has its `fileName` and `lineNumber` attributes
794/// set:
795/// @code
796/// ball::Record *record = logger->getRecord(fileName, lineNumber);
797/// @endcode
798/// Then, we get a non-`const` reference to the fixed fields of `record`:
799/// @code
800/// ball::RecordAttributes& attributes = record->fixedFields();
801/// @endcode
802/// Next, we create a `bsl::ostream` to which the string representation
803/// `information` can be output. Note that `stream` is supplied with the stream
804/// buffer of `attributes`:
805/// @code
806/// bsl::ostream stream(&attributes.messageStreamBuf());
807/// @endcode
808/// Then, we stream `information` into our output `stream`. This will set the
809/// message attribute of `record` to the streamed data:
810/// @code
811/// stream << information;
812/// @endcode
813/// Finally, we log `record` using `logger`:
814/// @code
815/// logger->logMessage(category, severity, record);
816/// }
817/// @endcode
818/// Notice that we did not need to allocate a scratch buffer to stream the
819/// object contents into. That would have required an extra copy and the cost
820/// of allocation and deallocation, and thus would have been more inefficient.
821///
822/// ### Example 4: Logging using a ball::Logger {#ball_loggermanager-example-4-logging-using-a-ball-logger}
823///
824///
825/// This example demonstrates using a `ball::Logger` directly to log messages.
826/// In practice, clients are encouraged to use the logging macros (see
827/// {`ball_log`}. The following example assumes logging has been correctly
828/// initialized (see prior examples).
829///
830/// The following simple `factorial` function takes and returns values of type
831/// `int`. Note that this function has a very limited range of input, namely
832/// integers in the range `[0 .. 13]`. This limited range serves to illustrate
833/// a usage pattern of the logger, namely to log "warnings" whenever a key
834/// function is given bad input.
835///
836/// For this example, it is sufficient to use the severity levels defined in the
837/// `ball::Severity::Level` enumeration:
838/// @code
839/// enum Level {
840/// e_OFF = 0, // disable generation of corresponding message
841/// e_FATAL = 32, // a condition that will (likely) cause a *crash*
842/// e_ERROR = 64, // a condition that *will* cause incorrect behavior
843/// e_WARN = 96, // a *potentially* problematic condition
844/// e_INFO = 128, // data about the running process
845/// e_DEBUG = 160, // information useful while debugging
846/// e_TRACE = 192 // execution trace data
847/// };
848/// @endcode
849/// Note that the intervals left between enumerator values allow applications
850/// to define additional values in case there is a desire to log with more
851/// finely-graduated levels of severity. We will not need that granularity
852/// here; `ball::Severity::e_WARN` is appropriate to log a warning message if
853/// the input argument to our factorial function is not in this range of values.
854///
855/// We will register a unique category for this function, so that logged
856/// messages from our function will be identified in the published output.
857/// Also, with a unique category name, the logging behavior of this function can
858/// be administered by resetting the various threshold levels for the category.
859/// In this example, we will accept the default thresholds.
860///
861/// The `setCategory` method accepts a name and returns the address of a
862/// `ball::Category` with that name or, in some circumstances, the address of
863/// the *Default* *Category* (see the function-level documentation of
864/// `setCategory` for details). The address returned by `setCategory` is stored
865/// in a function-static pointer variable (i.e., it is fetched only once upon
866/// first use). In this example, we assume that we are writing a function for
867/// Equities Graphics that will live in that group's Math library. The dot
868/// "delimiters" (`.`) have no particular significance to the logger, but may be
869/// used by the administration methods to "induce" a hierarchical behavior on
870/// our category, should that be useful. See, e.g., the callback functor
871/// `ball::LoggerManager::DefaultThresholdLevelsCallback` and its documentation,
872/// and Usage Example 2 above for information on how to use category names to
873/// customize logger behavior:
874/// @code
875/// /// Return the factorial of the specified value `n` if the factorial
876/// /// can be represented as an `int`, and a negative value otherwise.
877/// int factorial(int n)
878/// {
879/// static const ball::Category *factorialCategory =
880/// ball::LoggerManager::singleton().setCategory(
881/// "equities.graphics.math.factorial",
882/// ball::Severity::e_INFO,
883/// ball::Severity::e_TRACE,
884/// ball::Severity::e_ERROR,
885/// ball::Severity::e_FATAL);
886/// @endcode
887/// We must also obtain a reference to a logger by calling the logger manager
888/// `getLogger` method. Note that this logger may not safely be cached as a
889/// function `static` variable since our function may be called in different
890/// threads having different loggers. Even in a single-threaded program, the
891/// owner of `main` is free to install new loggers at any point, so a
892/// statically-cached logger would be a problem:
893/// @code
894/// ball::Logger& logger = ball::LoggerManager::singleton().getLogger();
895/// @endcode
896/// Now we validate the input value `n`. If `n` is either negative or too
897/// large, we will log a warning message (at severity level
898/// `ball::Severity::e_WARN`) and return a negative value. Note that calls to
899/// `logMessage` have no run-time overhead (beyond the execution of a simple
900/// `if` test) unless `ball::Severity::e_WARN` is at least as severe as one of
901/// the threshold levels of `factorialCategory`:
902/// @code
903/// if (0 > n) {
904/// logger.logMessage(*factorialCategory,
905/// ball::Severity::e_WARN,
906/// __FILE__,
907/// __LINE__,
908/// "Attempt to take factorial of negative value.");
909/// return n; // RETURN
910/// }
911///
912/// enum { MAX_ARGUMENT = 13 }; // maximum value accepted by 'factorial'
913///
914/// if (MAX_ARGUMENT < n) {
915/// logger.logMessage(*factorialCategory,
916/// ball::Severity::e_WARN,
917/// __FILE__,
918/// __LINE__,
919/// "Result too large for 'int'.");
920/// return -n; // RETURN
921/// }
922/// @endcode
923/// The remaining code proceeds mostly as expected, but adds one last message
924/// that tracks control flow when `ball::Severity::e_TRACE` is at least as
925/// severe as one of the threshold levels of `factorialCategory` (e.g., as
926/// might be the case during debugging):
927/// @code
928/// int product = 1;
929/// while (1 < n) {
930/// product *= n;
931/// --n;
932/// }
933///
934/// logger.logMessage(*factorialCategory,
935/// ball::Severity::e_TRACE,
936/// __FILE__,
937/// __LINE__,
938/// "Exiting 'factorial' successfully.");
939///
940/// return product;
941/// }
942/// @endcode
943/// @}
944/** @} */
945/** @} */
946
947/** @addtogroup bal
948 * @{
949 */
950/** @addtogroup ball
951 * @{
952 */
953/** @addtogroup ball_loggermanager
954 * @{
955 */
956
957#include <balscm_version.h>
958
959#include <ball_attribute.h>
963#include <ball_categorymanager.h>
965#include <ball_record.h>
966#include <ball_recordbuffer.h>
969#include <ball_transmission.h>
970
971#include <bdlcc_objectpool.h>
973
974#include <bdlma_concurrentpool.h>
975
976#include <bslma_allocator.h>
977#include <bslma_managedptr.h>
978
979#include <bslmt_mutex.h>
981
982#include <bsls_atomic.h>
984#include <bsls_performancehint.h>
985
986#include <bsl_functional.h>
987#include <bsl_map.h>
988#include <bsl_memory.h>
989#include <bsl_set.h>
990#include <bsl_string_view.h>
991
992
993namespace ball {
994
995class Context;
996class LoggerManager;
997class Observer;
998class RecordBuffer;
999
1000 // ============
1001 // class Logger
1002 // ============
1003
1004/// This class provides log record management services. Each instance of
1005/// `Logger` receives log records from one or more clients, manages the
1006/// storage of those records, and transmits them to a registered recipient
1007/// (i.e., an observer) when appropriate.
1008///
1009/// See @ref ball_loggermanager
1010class Logger {
1011
1012 public:
1013 // TYPES
1014
1015 /// `UserFieldsPopulatorCallback` is the type of a user-supplied
1016 /// callback functor used to populate the user-defined fields in each
1017 /// log record.
1020
1021 /// `PublishAllTriggerCallback` is the type of the functor that is
1022 /// invoked with the publication cause to publish all record buffers of
1023 /// all loggers that are allocated by the logger manager.
1025
1026 private:
1027 // DATA
1031 d_recordPool; // pool of records with a
1032 // custom 'RESETTER'
1033
1035 d_observer; // holds observer
1036
1037 RecordBuffer *d_recordBuffer_p; // holds log record buffer
1038 // (not owned)
1039
1041 d_userFieldsPopulator; // user fields populator
1042 // functor
1043
1045 *d_attributeCollectors_p; // pointer to the registry of
1046 // attribute collector
1047 // callbacks (not owned)
1048
1050 d_publishAll; // publishAll callback functor
1051
1053 d_bufferPool; // pool of buffers for
1054 // formatting log messages
1055 // allowing recursive access
1056
1057 char *d_scratchBuffer_p; // buffer for formatting log
1058 // messages (owned)
1059
1060 bslmt::Mutex d_scratchBufferMutex; // ensure thread-safety of
1061 // message buffer
1062
1063 int d_scratchBufferSize; // message buffer size (bytes)
1064
1066 d_logOrder; // logging order
1067
1069 d_triggerMarkers; // trigger markers
1070
1072 *d_allocator_p; // memory allocator (held, not
1073 // owned)
1074
1075 // FRIENDS
1076 friend class LoggerManager;
1077
1078 private:
1079 // NOT IMPLEMENTED
1080 Logger(const Logger&);
1081 Logger& operator=(const Logger&);
1082
1083 // PRIVATE CREATORS
1084
1085 /// Create a logger having the specified `observer` that receives
1086 /// published log records, the specified `recordBuffer` that stores log
1087 /// records, the specified `userFieldsPopulator` that populates the
1088 /// user-defined fields of log records, the specified
1089 /// `attributeCollectors` registry of user-installed attribute
1090 /// collectors, the specified `publishAllCallback` that is invoked when
1091 /// a Trigger-All event occurs, the specified `scratchBufferSize` for
1092 /// the internal message buffer accessible via `obtainMessageBuffer`,
1093 /// and the specified `globalAllocator` used to supply memory. On a
1094 /// Trigger or Trigger-All event, the messages are published in the specified `logOrder`.
1095 ///
1096 /// \note Note that this constructor is `private` since
1097 /// the creation of instances of `Logger` is managed by its `friend`
1098 /// `LoggerManager`.
1099 Logger(const bsl::shared_ptr<Observer>& observer,
1100 RecordBuffer *recordBuffer,
1101 const UserFieldsPopulatorCallback& userFieldsPopulator,
1102 const AttributeCollectorRegistry *attributeCollectors,
1103 const PublishAllTriggerCallback& publishAllCallback,
1104 int scratchBufferSize,
1107 bslma::Allocator *globalAllocator);
1108
1109 /// Destroy this logger.
1110 ~Logger();
1111
1112 // PRIVATE MANIPULATORS
1113
1114 /// Return a shared pointer to a modifiable record having the specified
1115 /// `fileName` and `lineNumber` attributes, and retrieved from the
1116 /// shared object pool managed by this logger.
1117 bsl::shared_ptr<Record> getRecordPtr(const bsl::string_view& fileName,
1118 int lineNumber);
1119
1120 /// Log the specified `record` after setting its category field to the
1121 /// specified `category`, severity field to the specified `severity`,
1122 /// and the rest of the fixed fields (except `fileName`, `lineNumber`,
1123 /// and `message`, all of which are assumed to be already set in
1124 /// `record`) based on the threshold levels of the specified `levels`.
1125 /// (See the component-level documentation of @ref ball_record for more
1126 /// information on the fields that are logged.) Store the record in the
1127 /// buffer held by this logger if `severity` is at least as severe as
1128 /// the "Record" threshold level of `levels`. Pass the record directly
1129 /// to the observers registered with this logger if `severity` is at
1130 /// least as severe as the "Pass" threshold level of `levels`. Publish
1131 /// the entire contents of the buffer of this logger if `severity` is at
1132 /// least as severe as the "Trigger" threshold level of `levels`.
1133 /// Publish the entire contents of all buffers of all active loggers if
1134 /// `severity` is at least as severe as the "Trigger-All" threshold
1135 /// level of `levels` (i.e., via the callback supplied at construction).
1136 /// Finally, dispose of `record`. This method has no effect (other than
1137 /// disposing of `record`) if `severity` is less severe than each of the threshold levels of `levels`.
1138 ///
1139 /// \pre The behavior is undefined unless
1140 /// `severity` is in the range `[1 .. 255]` and `record` was previously obtained via a call to `getRecord`.
1141 ///
1142 /// \note Note that `record` will be
1143 /// invalid after this method returns.
1144 void logMessage(const Category& category,
1145 int severity,
1146 const bsl::shared_ptr<Record>& record,
1147 const ThresholdAggregate& levels);
1148
1149 /// Publish to the observer held by this logger all records stored in
1150 /// the record buffer of this logger and indicate to the observer the
1151 /// specified publication `cause`.
1152 void publish(Transmission::Cause cause);
1153
1154 /// Publish to the observer held by this logger the specified `record` with
1155 /// the specified `context`.
1156 void publish(const bsl::shared_ptr<Record>& record,
1157 const Context& context);
1158
1159 public:
1160 // MANIPULATORS
1161
1162 /// Return the address of a modifiable record having the specified
1163 /// `fileName` and `lineNumber` attributes, and retrieved from the object pool managed by this logger.
1164 ///
1165 /// \note Note that the returned `Record`
1166 /// must subsequently be supplied to a call to the 3-argument
1167 /// `logMessage` method on this logger.
1168 Record *getRecord(const bsl::string_view& fileName, int lineNumber);
1169
1170 /// Log a record containing the specified `message` text, `fileName`,
1171 /// `lineNumber`, `severity`, and the name of the specified `category`.
1172 /// (See the component-level documentation of @ref ball_record for more
1173 /// information on the additional fields that are logged.) Store the
1174 /// record in the buffer held by this logger if `severity` is at least
1175 /// as severe as the current "Record" threshold level of `category`.
1176 /// Pass the record directly to the observer held by this logger if
1177 /// `severity` is at least as severe as the current "Pass" threshold
1178 /// level of `category`. Publish the entire contents of the buffer of
1179 /// this logger if `severity` is at least as severe as the current
1180 /// "Trigger" threshold level of `category`. Publish the entire
1181 /// contents of all buffers of all active loggers of this logger factory
1182 /// if `severity` is at least as severe as the current "Trigger-All"
1183 /// threshold level of `category` (i.e., via the callback supplied at construction).
1184 ///
1185 /// \note Note that this method will have no effect if
1186 /// `severity` is less severe than all of the threshold levels of `category`.
1187 ///
1188 /// \pre The behavior is undefined unless `severity` is in the
1189 /// range `[1 .. 255]`.
1190 void logMessage(const Category& category,
1191 int severity,
1192 const bsl::string_view& fileName,
1193 int lineNumber,
1194 const bsl::string_view& message);
1195
1196 /// Log the specified `*record` after setting its category attribute to
1197 /// the name of the specified `category` and severity attribute to the
1198 /// specified `severity`. (See the component-level documentation of
1199 /// @ref ball_record for more information on the fields that are logged.)
1200 /// Store the record in the buffer held by this logger if `severity` is
1201 /// at least as severe as the current "Record" threshold level of
1202 /// `category`. Pass the record directly to the observer held by this
1203 /// logger if `severity` is at least as severe as the current "Pass"
1204 /// threshold level of `category`. Publish the entire contents of the
1205 /// buffer of this logger if `severity` is at least as severe as the
1206 /// current "Trigger" threshold level of `category`. Publish the entire
1207 /// contents of all buffers of all active loggers if `severity` is at
1208 /// least as severe as the current "Trigger-All" threshold level of
1209 /// `category` (i.e., via the callback supplied at construction).
1210 /// Finally, dispose of `record`. This method has no effect (other than
1211 /// disposing of `record`) if `severity` is less severe than each of the threshold levels of `category`.
1212 ///
1213 /// \pre The behavior is undefined unless
1214 /// `severity` is in the range `[1 .. 255]`, both `fileName` and
1215 /// `message` are null-terminated, and `record` was previously obtained by a call to `getRecord` on this logger.
1216 ///
1217 /// \note Note that `record` will be
1218 /// invalid after this method returns.
1219 void logMessage(const Category& category,
1220 int severity,
1221 Record *record);
1222
1223#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1224 /// Return the address of the modifiable message buffer managed by this logger.
1225 ///
1226 /// \note Note that the returned buffer is intended to be used *only*
1227 /// for formatting log messages immediately before calling `logMessage`.
1228 ///
1229 /// @deprecated Use @ref obtainMessageBuffer instead. Do *not* use this
1230 /// method in multi-threaded code.
1231 char *messageBuffer();
1232#endif // BDE_OMIT_INTERNAL_DEPRECATED
1233
1234 /// Block until access to the buffer of this logger used for formatting
1235 /// messages is available. Return the address of the modifiable buffer
1236 /// to which this thread of execution has exclusive access, load the
1237 /// address of the mutex that protects the buffer into the specified
1238 /// `*mutex` address, and load the size (in bytes) of the buffer into
1239 /// the specified `bufferSize` address. The address remains valid, and
1240 /// the buffer remains locked by this thread of execution, until this thread calls `mutex->unlock()`.
1241 ///
1242 /// \pre The behavior is undefined if this
1243 /// thread of execution currently holds a lock on the buffer.
1244 ///
1245 /// \note Note that the buffer is intended to be used *only* for formatting log messages
1246 /// immediately before calling `logMessage`; other use may adversely
1247 /// affect performance for the entire program.
1248 char *obtainMessageBuffer(bslmt::Mutex **mutex, int *bufferSize);
1249
1250 /// Return a managed pointer that refers to the memory block to which
1251 /// this thread of execution has exclusive access and load the size (in
1252 /// bytes) of this buffer into the specified `bufferSize` address.
1253 ///
1254 /// \note Note that this method is intended for *internal* *use* only.
1256
1257 /// Publish to the observer held by this logger all records stored in
1258 /// the record buffer of this logger and indicate to the observer that
1259 /// the cause is `MANUAL_PUBLISH`.
1260 void publish();
1261
1262 /// Remove all log records from the record buffer of this logger.
1263 void removeAll();
1264
1265 // ACCESSORS
1266
1267 /// Return the size, in bytes, of the message buffer managed by this
1268 /// logger.
1269 int messageBufferSize() const;
1270
1271 /// Return a *snapshot* of number of records that have been dispensed by
1272 /// `getRecord` but have not yet been supplied (returned) using
1273 /// `logRecord`.
1274 int numRecordsInUse() const;
1275};
1276
1277#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1280#endif // BDE_OMIT_INTERNAL_DEPRECATED
1281
1282 // ===================
1283 // class LoggerManager
1284 // ===================
1285
1286/// This class is *usually* a singleton. It provides a factory for `Logger`
1287/// objects and is also a wrapper for category administration services.
1288///
1289/// \note Note that some services provided by this class are available only after
1290/// the singleton has been initialized.
1291///
1292/// See @ref ball_loggermanager
1294
1295 public:
1296 // TYPES
1297
1298 /// `CategoryNameFilterCallback` is the type of the user-supplied
1299 /// functor that translates external category names to internal names.
1301
1302 /// `DefaultThresholdLevelsCallback` is the type of the functor that
1303 /// determines default threshold levels for categories added to the
1304 /// registry by the `setCategory(const char *)` method.
1307
1308 /// `PublishAllTriggerCallback` is the type of the functor that is
1309 /// invoked to publish all record buffers of all active loggers (i.e.,
1310 /// loggers allocated by the logger manager that have not yet been
1311 /// deallocated).
1313
1314 /// `UserFieldsPopulatorCallback` is the type of a user-supplied
1315 /// callback functor used to populate the user-defined fields in each
1316 /// log record.
1319
1320 /// `AttributeCollector` is the type of a user-supplied functor used to
1321 /// visit a collection of attributes.
1323
1324 /// `AttributeVisitor` is the type of a user-supplied functor invoked
1325 /// by an attribute collector for every attribute.
1327
1328 /// This `typedef` is an alias for the type of the internal broadcast
1329 /// observer registry.
1331
1332 private:
1333 // NOT IMPLEMENTED
1335 LoggerManager& operator=(const LoggerManager&);
1336
1337#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1338 // FRIENDS
1341#endif // BDE_OMIT_INTERNAL_DEPRECATED
1342
1343 // CLASS DATA
1344 static LoggerManager *s_singleton_p; // address of singleton if
1345 // initialized; 0 otherwise
1346
1347 static bool s_isSingletonOwned; // `true` by default whereby
1348 // `ball` owns the singleton
1349 // and destroys it in
1350 // `shutDownSingleton`; can be
1351 // set to `false` by the
1352 // Windows-specific
1353 // `initSingleton` taking an
1354 // `adoptSingleton` flag
1355
1356 // DATA
1358 d_observer; // internal broadcast
1359 // observer
1360
1362 d_userFieldsPopulator;
1363 // user fields populator
1364 // functor
1365
1367 d_attributeCollectors;// Registered attribute
1368 // collector callbacks
1369
1370 Logger *d_logger_p; // holds default logger
1371 // (owned)
1372
1373 bsls::AtomicUint d_defaultLoggerCount; // number of thread-specific
1374 // default loggers
1375
1376 CategoryManager d_categoryManager; // category manager
1377
1378 bsl::set<Logger *> d_loggers; // set of *allocated* loggers
1379
1381 d_loggersLock; // `d_loggers` protector
1382
1383 RecordBuffer *d_recordBuffer_p; // holds record buffer (owned)
1384
1386 d_publishAllCallback; // self-installed callback
1387 // functor to publish all
1388 // records within process
1389 // (always valid)
1390
1391 int d_scratchBufferSize; // logger default message
1392 // buffer size (bytes)
1393
1395 d_defaultLoggers; // *registered* loggers
1396
1398 d_defaultLoggersLock; // registry lock
1399
1401 d_logOrder; // logging order
1402
1404 d_triggerMarkers; // trigger markers
1405
1406 bslma::Allocator *d_allocator_p; // memory allocator (held,
1407 // not owned)
1408
1409 // PRIVATE CLASS METHODS
1410
1411 /// Initialize the logger manager singleton having the specified
1412 /// `configuration` of defaults and attributes, and the specified
1413 /// `globalAllocator` used to supply memory. If `globalAllocator` is 0,
1414 /// the currently installed global allocator is used. This method has
1415 /// no effect (aside from logging a warning) if the logger manager singleton already exists.
1416 ///
1417 /// \pre The behavior is undefined unless the lock
1418 /// guarding the singleton is acquired before calling this method.
1419 ///
1420 /// \note Note that `singletonQLock`, an instance of `bslmt::QLock` local to the
1421 /// implementation file, enforces exclusive access to `s_singleton_p`
1422 /// during initialization and shutdown of the logger manager singleton.
1423 static void initSingletonImpl(
1424 const LoggerManagerConfiguration& configuration,
1425 bslma::Allocator *globalAllocator);
1426
1427 // PRIVATE CREATORS
1428
1429#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1430 /// Create a logger manager having the specified `observer` that
1431 /// receives published log records and the specified `configuration` of
1432 /// defaults and attributes. Optionally specify a `globalAllocator`
1433 /// used to supply memory. If `globalAllocator` is 0, the currently installed global allocator is used.
1434 ///
1435 /// \pre The behavior is undefined if
1436 /// `observer` is 0, goes out of scope, or is otherwise destroyed.
1437 ///
1438 /// \note Note that the new logger manager is *not* the singleton logger manager
1439 /// used by macros of the BALL logging framework.
1440 LoggerManager(const LoggerManagerConfiguration& configuration,
1442 bslma::Allocator *globalAllocator = 0);
1443#endif // BDE_OMIT_INTERNAL_DEPRECATED
1444
1445 // PRIVATE MANIPULATORS
1446
1447 /// Construct the default category, default logger members, and record
1448 /// buffer members of this logger manager based on the specified `configuration`.
1449 ///
1450 /// \pre The behavior is undefined if this method is
1451 /// invoked more than once on this logger manager.
1452 void constructObject(const LoggerManagerConfiguration& configuration);
1453
1454 /// Transmit to the observers registered with this logger manager all
1455 /// log records accumulated in the record buffers of all loggers managed
1456 /// by this logger manager and indicate to the observers the specified
1457 /// publication `cause`.
1458 void publishAllImp(Transmission::Cause cause);
1459
1460 /// Return a non-`const` reference to a logger managed by this logger
1461 /// manager suitable for performing logging operations for this thread
1462 /// of execution.
1463 Logger& getLoggerSlow();
1464
1465 public:
1466 // CLASS METHODS
1467#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1468 /// Create a logger manager that is *not* the singleton logger manager
1469 /// having the specified `observer` that receives published log records
1470 /// and the specified `configuration` of defaults and attributes; load
1471 /// the newly-created logger manager into the specified `manager`
1472 /// managed pointer. Optionally specify a `basicAllocator` used to
1473 /// supply memory. If `basicAllocator` is 0, the currently installed default allocator is used.
1474 ///
1475 /// \pre The behavior is undefined if `observer` is 0, goes out of scope, or is otherwise destroyed.
1476 ///
1477 /// \note Note that this
1478 /// method does *not* create the singleton logger manager used by the
1479 /// macros of the BALL logging framework.
1480 ///
1481 /// @deprecated Use @ref createLoggerManager method that does not
1482 /// take a *raw* pointer to an `observer`, together with the
1483 /// `registerObserver` method (which takes a *shared* pointer to an
1484 /// `observer`), instead.
1488 const LoggerManagerConfiguration& configuration,
1489 bslma::Allocator *basicAllocator = 0);
1490#endif // BDE_OMIT_INTERNAL_DEPRECATED
1491
1492 /// Create a logger manager that is *not* the singleton logger manager
1493 /// having the specified `configuration` of defaults and attributes;
1494 /// load the newly-created logger manager into the specified `manager`
1495 /// managed pointer. Optionally specify a `basicAllocator` used to
1496 /// supply memory. If `basicAllocator` is 0, the currently installed default allocator is used.
1497 ///
1498 /// \note Note that this method does *not* create
1499 /// the singleton logger manager used by the macros of the BALL logging
1500 /// framework.
1503 const LoggerManagerConfiguration& configuration,
1504 bslma::Allocator *basicAllocator = 0);
1505
1506 /// Return the address of a modifiable record with the specified
1507 /// `fileName` and `lineNumber` attributes, and whose memory is supplied by the currently installed default allocator.
1508 ///
1509 /// \note Note that the
1510 /// returned `Record` must subsequently be supplied to a call to the
1511 /// `LoggerManager::logMessage` method.
1512 static Record *getRecord(const bsl::string_view& fileName, int lineNumber);
1513
1514#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1515 /// Initialize the logger manager singleton having the specified
1516 /// `observer` that receives published log records. Optionally specify
1517 /// a `configuration` describing how the singleton should be configured.
1518 /// If `configuration` is not specified, a default constructed
1519 /// `LoggerManagerConfiguration` object is used. Optionally specify a
1520 /// `globalAllocator` used to supply memory. If `globalAllocator` is 0,
1521 /// the currently installed global allocator is used. Return a
1522 /// non-`const` reference to the logger manager singleton. This method
1523 /// has no effect (aside from logging a warning) if the logger manager singleton already exists.
1524 ///
1525 /// \pre The behavior is undefined if `observer`
1526 /// is 0, goes out of scope, or is otherwise destroyed.
1527 ///
1528 /// @deprecated Use @ref initSingleton method that does not take a
1529 /// *raw* pointer to an `observer`, together with the `registerObserver`
1530 /// method (which takes a *shared* pointer to an `observer`), instead.
1533 bslma::Allocator *globalAllocator = 0);
1536 const LoggerManagerConfiguration& configuration,
1537 bslma::Allocator *globalAllocator = 0);
1538#endif // BDE_OMIT_INTERNAL_DEPRECATED
1539
1540 /// Initialize the logger manager singleton. Optionally specify a
1541 /// `configuration` describing how the singleton should be configured.
1542 /// If `configuration` is not specified, a default constructed
1543 /// `LoggerManagerConfiguration` object is used. Optionally specify a
1544 /// `globalAllocator` used to supply memory. If `globalAllocator` is 0,
1545 /// the currently installed global allocator is used. Return a
1546 /// non-`const` reference to the logger manager singleton. This method
1547 /// has no effect (aside from logging a warning) if the logger manager
1548 /// singleton already exists.
1549 static LoggerManager& initSingleton(bslma::Allocator *globalAllocator = 0);
1551 const LoggerManagerConfiguration& configuration,
1552 bslma::Allocator *globalAllocator = 0);
1553
1554 /// Initialize the logger manager singleton with the specified
1555 /// `singleton`. Optionally specify an `adoptSingleton` flag indicating
1556 /// whether this method takes ownership of `singleton`, in which case
1557 /// `shutDownSingleton` will destroy `singleton`. If `adoptSingleton`
1558 /// is not specified, this method does *not* take ownership of
1559 /// `singleton` (and `shutDownSingleton` will not destroy it). Return 0
1560 /// if the logger manager singleton was successfully initialized, and a
1561 /// non-zero value otherwise. This method has no effect (aside from
1562 /// logging a warning) if the logger manager singleton already exists,
1563 /// in which case this method does *not* take ownership of `singleton` regardless of the value of `adoptSingleton`.
1564 ///
1565 /// \note Note that this version
1566 /// of `initSingleton` is meant for use *only* on Windows to initialize
1567 /// another dynamically loaded copy of the `LoggerManager` system. Also
1568 /// note that a suitable singleton may be obtained by calling
1569 /// `createLoggerManager`, or from the `singleton` class method of an
1570 /// already-initialized `LoggerManager` system.
1572 bool adoptSingleton = false);
1573
1574 /// Return `true` if the logger manager singleton exists, and `false`
1575 /// otherwise.
1576 static bool isInitialized();
1577
1578 /// Publish the specified `record` using
1579 /// `bsls::Log::platformDefaultMessageHandler` after setting its
1580 /// severity attribute to the specified `severity`, and dispose of `record`.
1581 ///
1582 /// \pre The behavior is undefined unless `record` was obtained by a call to the `LoggerManager::getRecord` method.
1583 ///
1584 /// \note Note that `record`
1585 /// will be invalid after this method returns.
1586 static void logMessage(int severity, Record *record);
1587
1588 /// Block until access to the static buffer used for formatting messages
1589 /// is available. Return the address of the modifiable buffer to which
1590 /// this thread of execution has exclusive access, load the address of
1591 /// the mutex that protects the buffer into the specified `*mutex`
1592 /// address, and load the size (in bytes) of the buffer into the
1593 /// specified `bufferSize` address. The address remains valid, and the
1594 /// buffer remains locked by this thread of execution, this thread calls `mutex->unlock()`.
1595 ///
1596 /// \pre The behavior is undefined if this thread of execution currently holds a lock on the buffer.
1597 ///
1598 /// \note Note that the
1599 /// buffer is intended to be used *only* for formatting log messages
1600 /// immediately before calling `logMessage`; other use may adversely
1601 /// affect performance for the entire program.
1602 static char *obtainMessageBuffer(bslmt::Mutex **mutex, int *bufferSize);
1603
1604 /// Return a managed pointer that refers to the memory block to which
1605 /// this thread of execution has exclusive access and load the size (in
1606 /// bytes) of this buffer into the specified `bufferSize` address.
1607 ///
1608 /// \note Note that this method is intended for *internal* *use* only.
1610
1611 /// Destroy the logger manager singleton and release all resources used
1612 /// by it. This method has no effect if the logger manager singleton
1613 /// does not exist (i.e., it has not been initialized or has already been destroyed).
1614 ///
1615 /// \pre The behavior is undefined if this method is called
1616 /// from one thread while another thread is accessing the logger manager
1617 /// singleton (i.e., this method is *not* thread-safe).
1618 static void shutDownSingleton();
1619
1620 /// Return a non-`const` reference to the logger manager singleton.
1621 ///
1622 /// \pre The behavior is undefined unless the logger manager singleton exists.
1623 static LoggerManager& singleton();
1624
1625 // CREATORS
1626
1627 /// Create a logger manager having the specified `configuration` of
1628 /// defaults and attributes. Optionally specify a `globalAllocator`
1629 /// used to supply memory. If `globalAllocator` is 0, the currently installed global allocator is used.
1630 ///
1631 /// \note Note that the new logger
1632 /// manager is *not* the singleton logger manager used by macros of the
1633 /// BALL logging framework.
1635 const LoggerManagerConfiguration& configuration,
1636 bslma::Allocator *globalAllocator = 0);
1637
1638 /// Destroy this logger manager.
1640
1641 // MANIPULATORS
1642 // Logger Management
1643
1644 /// Return the address of a modifiable logger managed by this logger
1645 /// manager configured with the specified record `buffer`. Optionally
1646 /// specify a `scratchBufferSize` for the logger's user-accessible
1647 /// message buffer. If `scratchBufferSize` is not specified, the value configured at construction is used.
1648 ///
1649 /// \note Note that this method is
1650 /// primarily intended for use in multi-threaded applications, but can
1651 /// be used to partition logging streams even within a single thread.
1652 /// Also note that ownership of `buffer` is *not* transferred, and
1653 /// hence, will *not* be destroyed (or otherwise affected) after the
1654 /// logger is deallocated.
1656 Logger *allocateLogger(RecordBuffer *buffer, int scratchBufferSize);
1657
1658#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1659 /// Return the address of a modifiable logger managed by this logger
1660 /// manager having the specified `observer` that receives published log
1661 /// records and configured with the specified record `buffer`.
1662 /// Optionally specify a `scratchBufferSize` for the logger's
1663 /// user-accessible message buffer. If `scratchBufferSize` is not
1664 /// specified, the value configured at construction is used.
1665 ///
1666 /// \note Note that this method is primarily intended for use in multi-threaded
1667 /// applications, but can be used to partition logging streams even
1668 /// within a single thread. Also note that ownership of `buffer` and
1669 /// `observer` is *not* transferred, and hence, will *not* be destroyed
1670 /// (or otherwise affected) after the logger is deallocated.
1671 ///
1672 /// @deprecated Use @ref allocateLogger method that does not take a
1673 /// *raw* pointer to an `observer`, together with the `registerObserver`
1674 /// method (which takes a *shared* pointer to an `observer`), instead.
1678 int scratchBufferSize,
1680#endif // BDE_OMIT_INTERNAL_DEPRECATED
1681
1682 /// Return the address of a modifiable logger managed by this logger
1683 /// manager having the specified `observer` that receives published log
1684 /// records and configured with the specified record `buffer`.
1685 /// Optionally specify a `scratchBufferSize` for the logger's
1686 /// user-accessible message buffer. If `scratchBufferSize` is not
1687 /// specified, the value configured at construction is used.
1688 ///
1689 /// \note Note that this method is primarily intended for use in multi-threaded
1690 /// applications, but can be used to partition logging streams even
1691 /// within a single thread. Also note that ownership of `buffer` and
1692 /// `observer` is *not* transferred, and hence, will *not* be destroyed
1693 /// (or otherwise affected) after the logger is deallocated.
1697 int scratchBufferSize,
1699
1700 /// Deallocate the specified `logger` and release `logger` from management by this logger manager.
1701 ///
1702 /// \pre The behavior is undefined unless
1703 /// `logger` was obtained by invoking the `allocateLogger` method of
1704 /// this logger manager and `logger` has not yet been deallocated.
1705 ///
1706 /// \note Note that this method is intended primarily for multi-threaded
1707 /// applications.
1709
1710 /// Return a non-`const` reference to a logger managed by this logger
1711 /// manager suitable for performing logging operations for this thread
1712 /// of execution.
1713 Logger& getLogger();
1714
1715 /// Set the default logger used by this thread of execution to the
1716 /// specified `logger`, or to the global default logger if `logger` is 0.
1717 ///
1718 /// \pre The behavior is undefined unless `logger` was obtained from this
1719 /// logger manager, and this thread of execution does not hold exclusive
1720 /// access to the record buffer of its current default logger.
1721 void setLogger(Logger *logger);
1722
1723 // Category Management
1724
1725 /// Add a new category having the specified `categoryName`; return the
1726 /// address of the modifiable new category on success, and 0, with no
1727 /// effect, if a category by that name already exists or if the number of
1728 /// existing categories has reached the maximum capacity. The newly
1729 /// created category will have its threshold levels chosen primarily from
1730 /// two sources: threshold levels of an existing category or a category
1731 /// setting (to which no category exists) choosing the one whose name is
1732 /// the longest non-empty prefix of `categoryName`. If such a category or
1733 /// setting exists, and the default threshold levels (which might be
1734 /// overridden by a default threshold levels callback) otherwise. See also
1735 /// `ball::CategoryManager::addCategoryHierarchically`.
1736 Category *addCategoryHierarchically(const char *categoryName);
1737
1738 /// Add to the category registry of this logger manager a new category
1739 /// having the specified `categoryName` and the specified `recordLevel`,
1740 /// `passLevel`, `triggerLevel`, and `triggerAllLevel` threshold levels,
1741 /// respectively, if (1) `categoryName` is not present in the registry,
1742 /// (2) the number of categories in the registry is less than the
1743 /// registry capacity, and (3) each threshold level is in the range
1744 /// `[0 .. 255]`. Return the address of the new modifiable category on success, and 0 otherwise.
1745 ///
1746 /// \pre The behavior is undefined unless
1747 /// `categoryName` is null-terminated.
1748 Category *addCategory(const char *categoryName,
1749 int recordLevel,
1750 int passLevel,
1751 int triggerLevel,
1752 int triggerAllLevel);
1753
1754 /// Return a non-`const` reference to the *Default* *Category* in the
1755 /// category registry of this logger manager.
1757
1758 /// Return the address of the modifiable category in the category
1759 /// registry of this logger manager having the specified `categoryName`, or 0 if no such category exists.
1760 ///
1761 /// \pre The behavior is undefined unless
1762 /// `categoryName` is null-terminated.
1763 Category *lookupCategory(const char *categoryName);
1764
1765 /// Add to the category registry of this logger manager a new category
1766 /// having the specified `categoryName` and default threshold levels if
1767 /// `categoryName` is not present in the registry and the number of
1768 /// categories in the registry is less than the registry capacity.
1769 /// Return the address of the (possibly newly-created) non-modifiable
1770 /// category having `categoryName`, if such a category exists, and the
1771 /// address of the non-modifiable *Default* *Category* otherwise.
1772 ///
1773 /// \pre The behavior is undefined unless `categoryName` is null-terminated.
1774 ///
1775 /// \note Note that a valid category address is *always* returned.
1776 const Category *setCategory(const char *categoryName);
1777
1778 /// Add to the category registry of this logger manager a new category
1779 /// having the specified `categoryName` and default threshold levels if
1780 /// `categoryName` is not present in the registry and the number of
1781 /// categories in the registry is less than the registry capacity.
1782 /// Return the address of the (possibly newly-created) non-modifiable
1783 /// category having `categoryName`, if such a category exists, and the
1784 /// address of the non-modifiable *Default* *Category* otherwise. If
1785 /// the specified `categoryHolder` is non-null, then also load into
1786 /// `categoryHolder` the returned category and its maximum level and
1787 /// link `categoryHolder` to the category if it has not yet been linked.
1788 ///
1789 /// \pre The behavior is undefined unless `categoryName` is null-terminated.
1790 ///
1791 /// \note Note that a valid category address is *always* returned.
1792 const Category *setCategory(CategoryHolder *categoryHolder,
1793 const char *categoryName);
1794
1795 /// Add to the category registry of this logger manager a new category
1796 /// having the specified `categoryName` and `recordLevel`, `passLevel`,
1797 /// `triggerLevel`, and `triggerAllLevel` threshold levels,
1798 /// respectively, if (1) `categoryName` is not present in the registry,
1799 /// (2) the number of categories in the registry is less than the
1800 /// registry capacity, and (3) `recordLevel`, `passLevel`,
1801 /// `triggerLevel`, and `triggerAllLevel` are all within the range
1802 /// `[0 .. 255]`. If `categoryName` is already present and each
1803 /// threshold level is within the valid range then reset the threshold
1804 /// levels of `categoryName` to the specified values. Return the
1805 /// address of the (possibly newly-created) modifiable category having
1806 /// `categoryName` if `categoryName` was either created or its thresholds reset, and 0 otherwise.
1807 ///
1808 /// \pre The behavior is undefined unless `categoryName` is null-terminated.
1809 ///
1810 /// \note Note that 0, and *not* the
1811 /// *Default* *Category*, is returned on failure.
1812 Category *setCategory(const char *categoryName,
1813 int recordLevel,
1814 int passLevel,
1815 int triggerLevel,
1816 int triggerAllLevel);
1817
1818 /// Set the capacity of the category registry of this logger manager to
1819 /// the specified `length`. If `length` is 0, no limit will be imposed.
1820 /// No categories are removed from the registry if the current number of
1821 /// categories exceeds `length`. However, subsequent attempts to add
1822 /// categories to the registry will fail.
1823 ///
1824 /// \pre The behavior is undefined unless `0 <= length`.
1825 void setMaxNumCategories(int length);
1826
1827 // Observer Management
1828
1829 /// Remove all observers from the registry of observers maintained by
1830 /// this logger manager.
1832
1833 /// Remove the observer having the specified `observerName` from the
1834 /// registry of observers maintained by this logger manager. Return 0
1835 /// if the observer having `observerName` was successfully deregistered
1836 /// from this logger manager, and a non-zero value (with no effect)
1837 /// otherwise. Henceforth, the observer that had `observerName` will no
1838 /// longer receive log records published by this logger manager.
1839 int deregisterObserver(const bsl::string_view& observerName);
1840
1841 /// Remove the attribute collector having the specified `collectorName`
1842 /// from the registry of collectors maintained by this logger manager.
1843 /// Return 0 if the collector having `collectorName` was successfully
1844 /// deregistered from this logger manager, and a non-zero value (with no
1845 /// effect) otherwise.
1846 int deregisterAttributeCollector(const bsl::string_view& collectorName);
1847
1848 /// Return a shared pointer to the observer having the specified
1849 /// `observerName` in the registry of this logger manager, and an empty
1850 /// shared pointer if there is no such observer otherwise.
1852 const bsl::string_view& observerName);
1853
1854 /// Load into the specified `result` a shared pointer to the observer of
1855 /// (template parameter) `t_OBSERVER` type having the specified
1856 /// `observerName` in the registry of this logger manager, and an empty
1857 /// shared pointer if there is no such observer otherwise. Return 0 if
1858 /// a non-empty shared pointer was loaded, and a non-zero value otherwise.
1859 ///
1860 /// \note Note that an empty shared pointer will be loaded if
1861 /// either no observer having `observerName` is in the registry or the
1862 /// observer registered with that name is not of `t_OBSERVER` type.
1863 template <class t_OBSERVER>
1865 const bsl::string_view& observerName);
1866
1867#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1868 /// Return the address of the modifiable legacy observer registered with
1869 /// this logger manager.
1870 ///
1871 /// @deprecated Use @ref findObserver instead.
1873#endif // BDE_OMIT_INTERNAL_DEPRECATED
1874
1875 /// Add the specified `observer` with the specified `observerName` to
1876 /// the registry of observers maintained by this logger manager. Return
1877 /// 0 if `observer` was successfully registered with this logger
1878 /// manager, and a non-zero value (with no effect) otherwise.
1879 /// Henceforth, all log records published by this logger manager are
1880 /// published to this observer, until `observer` is deregistered.
1881 ///
1882 /// \pre The behavior is undefined if a cyclic reference is created among registered observers.
1883 ///
1884 /// \note Note that this method will fail if an
1885 /// observer having `observerName` is already registered.
1887 const bsl::string_view& observerName);
1888
1889 /// Add the specified `collector` with the specified `collectorName` to
1890 /// the registry of attribute collectors maintained by this logger
1891 /// manager. Return 0 if `collector` was successfully registered with
1892 /// this logger manager, and a non-zero value (with no effect) otherwise.
1893 ///
1894 /// \note Note that this method will fail if a collector having
1895 /// `collectorName` is already registered.
1897 const bsl::string_view& collectorName);
1898
1899 // Threshold Level Management Manipulators
1900
1901 /// Reset the default threshold levels of this logger manager to the
1902 /// original "factory-supplied" default values or the factory overrides
1903 /// supplied at construction.
1905
1906 /// Set the threshold levels of the specified `category` in the category
1907 /// registry of this logger manager to the current default threshold values.
1908 ///
1909 /// \pre The behavior is undefined unless `category` is non-null.
1911
1912 /// Set the threshold levels of the specified `category` in the category
1913 /// registry of this logger manager to the original "factory-supplied"
1914 /// default values or the factory overrides supplied at construction.
1915 ///
1916 /// \pre The behavior is undefined unless `category` is non-null.
1918
1919 /// Set the default threshold levels of this logger manager to the
1920 /// specified `recordLevel`, `passLevel`, `triggerLevel`, and
1921 /// `triggerAllLevel` values, respectively, if each threshold level is
1922 /// in the range `[0 .. 255]`. Return 0 on success, and a non-zero
1923 /// value otherwise (with no effect on any default threshold level).
1924 int setDefaultThresholdLevels(int recordLevel,
1925 int passLevel,
1926 int triggerLevel,
1927 int triggerAllLevel);
1928
1929 /// Set the default-thresholds callback of this logger manager to the
1930 /// specified `callback`. The default-thresholds callback is used to
1931 /// determine default threshold levels for categories added to the
1932 /// registry by the `setCategory(const char *)` method.
1935
1936 /// In case the specified `categoryNamePrefix` is not empty set the
1937 /// threshold levels of every existing and future category whose name has,
1938 /// as a prefix, `categoryNamePrefix` to the specified threshold values,
1939 /// `recordLevel`, `passLevel`, `triggerLevel`, and `triggerAllLevel`. In
1940 /// case `categoryNamePrefix` is empty set the threshold level of every
1941 /// existing category, and remove all preliminary settings (for future
1942 /// categories). Return the number of categories whose threshold levels
1943 /// were set, or a negative value, with no effect, if any of the specified
1944 /// threshold values is outside the range `[0 .. 255]`. See also
1945 /// `ball::CategoryManager::setThresholdLevelsHierarchically`.
1946 int setThresholdLevelsHierarchically(const char *categoryNamePrefix,
1947 int recordLevel,
1948 int passLevel,
1949 int triggerLevel,
1950 int triggerAllLevel);
1951
1952 // Rule Management
1953
1954 /// Add a rule having the specified `value` to the set of (unique)
1955 /// rules maintained by this object. Return the number of rules added
1956 /// (i.e., 1 on success and 0 if a rule with the same value is already
1957 /// present).
1958 int addRule(const Rule& value);
1959
1960 /// Add each rule in the specified `ruleSet` to the set of (unique)
1961 /// rules maintained by this object. Return the number of rules added.
1962 ///
1963 /// \note Note that each rule having the same value as an existing rule will
1964 /// be ignored.
1965 int addRules(const RuleSet& ruleSet);
1966
1967 /// Remove every rule from the set of rules maintained by this object.
1968 void removeAllRules();
1969
1970 /// Remove the rule having the specified `value` from this set of rules
1971 /// maintained by this object. Return the number of rules removed
1972 /// (i.e., 1 on success and 0 if no rule having the same value is
1973 /// found.)
1974 int removeRule(const Rule& value);
1975
1976 /// Remove each rule in the specified `ruleSet` from this set of rules
1977 /// maintained by this object. Return the number of rules removed.
1978 int removeRules(const RuleSet& ruleSet);
1979
1980 // Miscellaneous
1981
1982 /// Transmit to the observers registered with this logger manager all
1983 /// log records accumulated in the record buffers of all loggers managed
1984 /// by this logger manager, and indicate the publication cause to be
1985 /// `MANUAL_PUBLISH_ALL`.
1986 void publishAll();
1987
1988 /// Invoke the specified `visitor` functor on each category managed by
1989 /// this object, providing that functor modifiable access to each
1990 /// category. `visitor` must be a functor that can be called as if it
1991 /// had the following signature:
1992 /// @code
1993 /// void operator()(Category *);
1994 /// @endcode
1995 template <class t_CATEGORY_VISITOR>
1996 void visitCategories(const t_CATEGORY_VISITOR& visitor);
1997
1998 /// Invoke the specified `visitor` functor of (template parameter)
1999 /// `t_OBSERVER_VISITOR` type on each element in the registry of this
2000 /// logger manager, supplying that functor modifiable access to each
2001 /// observer. `visitor` must be a functor that can be called as if it
2002 /// had the following signature:
2003 /// @code
2004 /// void operator()(const bsl::shared_ptr<Observer>& observer,
2005 /// const bsl::string_view& observerName);
2006 /// @endcode
2007 template <class t_OBSERVER_VISITOR>
2008 void visitObservers(
2009 BSLS_COMPILERFEATURES_FORWARD_REF(t_OBSERVER_VISITOR) visitor);
2010
2011 // ACCESSORS
2012
2013 /// Return the address of the modifiable allocator held by this logger
2014 /// manager.
2015 bslma::Allocator *allocator() const;
2016
2017 /// Return a `const` reference to the *Default* *Category* in the
2018 /// category registry of this logger manager.
2019 const Category& defaultCategory() const;
2020
2021 /// Return the default pass threshold level of this logger manager.
2022 int defaultPassThresholdLevel() const;
2023
2024 /// Return the default record threshold level of this logger manager.
2025 int defaultRecordThresholdLevel() const;
2026
2027 /// Return the default trigger-all threshold level of this logger
2028 /// manager.
2030
2031 /// Return the default trigger threshold level of this logger manager.
2032 int defaultTriggerThresholdLevel() const;
2033
2034 /// Return a shared pointer to the observer having the specified
2035 /// `observerName` in the registry of this logger manager, and an empty
2036 /// shared pointer if there is no such observer otherwise.
2038 const bsl::string_view& observerName) const;
2039
2040 /// Load into the specified `result` a shared pointer to the observer of
2041 /// (template parameter) `t_OBSERVER` type having the specified
2042 /// `observerName` in the registry of this logger manager, and an empty
2043 /// shared pointer if there is no such observer otherwise. Return 0 if
2044 /// a non-empty shared pointer was loaded, and a non-zero value otherwise.
2045 ///
2046 /// \note Note that an empty shared pointer will be loaded if
2047 /// either no observer having `observerName` is in the registry or the
2048 /// observer registered with that name is not of `t_OBSERVER` type.
2049 template <class t_OBSERVER>
2051 const bsl::string_view& observerName) const;
2052
2053 /// Return `true` if the specified `severity` is more severe (i.e., is
2054 /// numerically less than) at least one of the threshold levels of the
2055 /// specified `category`, and `false` otherwise. If the returned
2056 /// `value` is `false`, then a subsequent call to
2057 /// `getLogger().logMessage()` (with `category` and `severity`) will
2058 /// have no effect. This method compares `severity` with the threshold
2059 /// levels determined by combining `category->thresholdLevels()` with
2060 /// the thresholds provided by any relevant and active logging rules (in `ruleSet()`) that apply to `category`.
2061 ///
2062 /// \note Note that a rule applies to
2063 /// `category` if the rule's pattern matches `category->categoryName()`,
2064 /// and a rule is active if all the predicates defined for that rule are
2065 /// satisfied by the current thread's attributes (i.e.,
2066 /// `Rule::evaluate()` returns `true` for the collection of attributes
2067 /// maintained by the current thread's `AttributeContext` object).
2068 bool isCategoryEnabled(const Category *category, int severity) const;
2069
2070 /// Return the address of the non-modifiable category in the category
2071 /// registry of this logger manager having the specified `categoryName`, or 0 if no such category exists.
2072 ///
2073 /// \pre The behavior is undefined unless
2074 /// `categoryName` is null-terminated.
2075 const Category *lookupCategory(const char *categoryName) const;
2076
2077 /// Return the current capacity of the category registry of this logger
2078 /// manager. A capacity of 0 implies that no limit will be imposed;
2079 /// otherwise, new categories may be added only if
2080 /// `numCategories() < maxNumCategories()`.
2081 ///
2082 /// \note Note that `0 < maxNumCategories() < numCategories()` *is* a valid state,
2083 /// implying no new categories may be added.
2084 int maxNumCategories() const;
2085
2086 /// Return the number of categories in the category registry of this
2087 /// logger manager.
2088 int numCategories() const;
2089
2090#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2091 /// Return the address of the non-modifiable observer registered with
2092 /// this logger manager.
2093 ///
2094 /// @deprecated Use @ref findObserver instead.
2095 const Observer *observer() const;
2096#endif // BDE_OMIT_INTERNAL_DEPRECATED
2097
2098 /// Return a `const` reference to the rule set maintained by this
2099 /// object.
2100 const RuleSet& ruleSet() const;
2101
2102 /// Return the address of the non-modifiable user populator functor
2103 /// registered with this logger manager, or 0 if there is no registered
2104 /// user populator functor.
2106
2107 /// Invoke the specified `visitor` functor on each category managed by
2108 /// this object, providing that functor non-modifiable access to each
2109 /// category. `visitor` must be a functor that can be called as if it
2110 /// had the following signature:
2111 /// @code
2112 /// void operator()(const Category *);
2113 /// @endcode
2114 template <class t_CATEGORY_VISITOR>
2115 void visitCategories(const t_CATEGORY_VISITOR& visitor) const;
2116
2117 /// Invoke the specified `visitor` functor of (template parameter)
2118 /// `t_OBSERVER_VISITOR` type on each element in the registry of this
2119 /// logger manager, supplying that functor modifiable access to each
2120 /// observer. `visitor` must be a functor that can be called as if it
2121 /// had the following signature:
2122 /// @code
2123 /// void operator()(const bsl::shared_ptr<Observer>& observer,
2124 /// const bsl::string_view& observerName);
2125 /// @endcode
2126 template <class t_OBSERVER_VISITOR>
2127 void visitObservers(
2128 BSLS_COMPILERFEATURES_FORWARD_REF(t_OBSERVER_VISITOR) visitor) const;
2129
2130 // Threshold Level Management Accessors
2131
2132 /// Return the default threshold levels associated with this logger
2133 /// manager object.
2135
2136 /// Load into the specified `*levels` the threshold levels that would be
2137 /// set for a newly created category, irrespective of whether a category
2138 /// with the specified `categoryName` is already in the registry.
2139 /// Return 0 on success and a non-zero value otherwise. If the client
2140 /// has configured a default threshold levels callback (see
2141 /// `ball::LoggerManager::DefaultThresholdLevelsCallback` in the
2142 /// component doc), the `categoryName` will be supplied to that callback
2143 /// which will set `*levels`. Otherwise, if no default threshold levels
2144 /// callback has been provided, the default threshold levels are used.
2145 ///
2146 /// \note Note that this function will report an error if the callback returns
2147 /// invalid levels. Also note that if a category named `categoryName`
2148 /// is already in the registry, the levels returned by this method may
2149 /// differ from the levels of that category.
2151 const char *categoryName) const;
2152};
2153
2154 // ==============================
2155 // class LoggerManagerScopedGuard
2156 // ==============================
2157
2158/// This class implements a scoped guard that, on construction, creates the
2159/// logger manager singleton, and, on destruction, destroys the singleton.
2160///
2161/// See @ref ball_loggermanager
2163
2164 private:
2165 // NOT IMPLEMENTED
2168
2169 public:
2170 // CREATORS
2171#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2172 /// Create a scoped guard that will create the logger manager singleton
2173 /// having the specified `observer` that receives published log records
2174 /// and the specified `configuration` of defaults and attributes.
2175 /// Optionally specify a `globalAllocator` used to supply memory. If
2176 /// `globalAllocator` is 0, the currently installed global allocator is
2177 /// used. This method has no effect (aside from logging a warning) if
2178 /// the logger manager singleton already exists.
2179 ///
2180 /// \pre The behavior is undefined if `observer` is 0, goes out of scope, or is otherwise destroyed.
2181 ///
2182 /// \note Note that on destruction, this scoped guard will destroy
2183 /// the logger manager singleton, if the singleton exists at that time.
2184 ///
2185 /// @deprecated Use @ref LoggerManagerScopedGuard constructor that
2186 /// does not take a *raw* pointer to an `observer`, together with the
2187 /// `registerObserver` method (which takes a *shared* pointer to an
2188 /// `observer`), instead.
2190 Observer *observer,
2191 const LoggerManagerConfiguration& configuration,
2192 bslma::Allocator *globalAllocator = 0);
2193#endif // BDE_OMIT_INTERNAL_DEPRECATED
2194
2195 /// Create a scoped guard that will create the logger manager singleton
2196 /// having the specified `configuration` of defaults and attributes.
2197 /// Optionally specify a `globalAllocator` used to supply memory. If
2198 /// `globalAllocator` is 0, the currently installed global allocator is
2199 /// used. This method has no effect (aside from logging a warning) if the logger manager singleton already exists.
2200 ///
2201 /// \note Note that on
2202 /// destruction, this scoped guard will destroy the logger manager
2203 /// singleton, if the singleton exists at that time.
2204 explicit LoggerManagerScopedGuard(
2205 const LoggerManagerConfiguration& configuration,
2206 bslma::Allocator *globalAllocator = 0);
2207
2208 /// Destroy the logger manager singleton, if the singleton exists, and
2209 /// destroy this scoped guard.
2211};
2212
2213#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2214
2215 // ===============================
2216 // class LoggerManagerCategoryIter
2217 // ===============================
2218
2219/// This class defines an iterator providing sequential, read-only access to
2220/// the categories in the registry of a logger manager's category manager.
2221/// The order of the iteration is undefined.
2222///
2223/// @deprecated Use @ref LoggerManager::visitCategories accessor instead.
2224///
2225/// See @ref ball_loggermanager
2227
2228 // DATA
2229 CategoryManagerIter d_iter; // contained category manager iterator
2230
2231 private:
2232 // NOT IMPLEMENTED
2235
2236 public:
2237 // CREATORS
2238
2239 /// Create an iterator providing non-modifiable access to the categories
2240 /// maintained by the specified `loggerManager` that is initialized to
2241 /// refer to the first category in the sequence of categories in the
2242 /// registry of `loggerManager`, if one exists, and is initialized to be
2243 /// invalid otherwise. The order of iteration is undefined.
2244 ///
2245 /// \pre The behavior is undefined unless the lifetime of `loggerManager` is at
2246 /// least as long as the lifetime of this iterator.
2247 explicit LoggerManagerCategoryIter(const LoggerManager& loggerManager);
2248
2250 // Destroy this iterator.
2251
2252 // MANIPULATORS
2253
2254 /// Advance this iterator to refer to the next unvisited category. If
2255 /// no such category exists, this iterator becomes invalid.
2256 ///
2257 /// \pre The behavior is undefined unless this iterator is initially valid.
2258 ///
2259 /// \note Note that the order of iteration is undefined.
2260 void operator++();
2261
2262 // ACCESSORS
2263
2264 /// Return a non-zero value if this iterator is valid, and 0 otherwise.
2265 operator const void *() const;
2266
2267 /// Return a `const` reference to the category currently referred to by this iterator.
2268 ///
2269 /// \pre The behavior is undefined unless this iterator is
2270 /// valid.
2271 const Category& operator()() const;
2272};
2273
2274 // ================================
2275 // class LoggerManagerCategoryManip
2276 // ================================
2277
2278/// This class defines an iterator providing sequential, modifiable access
2279/// to the categories in the registry of a logger manager's category
2280/// manager. The order of the iteration is undefined.
2281///
2282/// @deprecated Use @ref LoggerManager::visitCategories manipulator instead.
2283///
2284/// See @ref ball_loggermanager
2286
2287 // DATA
2288 CategoryManagerManip d_manip; // contained category manager iterator
2289
2290 private:
2291 // NOT IMPLEMENTED
2294
2295 public:
2296 // CREATORS
2297
2298 /// Create an iterator providing modifiable access to the categories
2299 /// maintained by the specified `loggerManager` that is initialized to
2300 /// refer to the first category in the sequence of categories in the
2301 /// registry of `loggerManager`, if one exists, and is initialized to be
2302 /// invalid otherwise. The order of iteration is undefined.
2303 ///
2304 /// \pre The behavior is undefined unless the lifetime of `loggerManager` is at
2305 /// least as long as the lifetime of this iterator.
2306 explicit LoggerManagerCategoryManip(LoggerManager *loggerManager);
2307
2308 // Destroy this iterator.
2310
2311 // MANIPULATORS
2312
2313 /// Advance this iterator to refer to the next unvisited category. If
2314 /// no such category exists, this iterator becomes invalid.
2315 ///
2316 /// \pre The behavior is undefined unless this iterator is initially valid.
2317 ///
2318 /// \note Note that the order of iteration is undefined.
2319 void advance();
2320
2321 /// Return a non-`const` reference to the category currently referred to by this iterator.
2322 ///
2323 /// \pre The behavior is undefined unless this iterator is
2324 /// valid.
2326
2327 // ACCESSORS
2328
2329 /// Return a non-zero value if this iterator is valid, and 0 otherwise.
2330 operator const void *() const;
2331};
2332
2333#endif // BDE_OMIT_INTERNAL_DEPRECATED
2334
2335// ============================================================================
2336// INLINE DEFINITIONS
2337// ============================================================================
2338
2339 // ------------
2340 // class Logger
2341 // ------------
2342
2343// MANIPULATORS
2344#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2345inline
2347{
2348 return d_scratchBuffer_p;
2349}
2350#endif // BDE_OMIT_INTERNAL_DEPRECATED
2351
2352inline
2357
2358inline
2360{
2361 d_recordBuffer_p->removeAll();
2362}
2363
2364// ACCESSORS
2365inline
2367{
2368 return d_scratchBufferSize;
2369}
2370
2371inline
2373{
2374 return d_recordPool.numObjects() - d_recordPool.numAvailableObjects();
2375}
2376
2377 // -------------------
2378 // class LoggerManager
2379 // -------------------
2380
2381// CLASS METHODS
2382inline
2384{
2385 return (LoggerManager *)0 != s_singleton_p;
2386}
2387
2388inline
2390{
2391 return *s_singleton_p;
2392}
2393
2394// MANIPULATORS
2395 // Category Management
2396
2397inline
2399{
2400 BSLS_ASSERT(categoryName);
2401 return d_categoryManager.addCategoryHierarchically(categoryName);
2402}
2403
2404inline
2406{
2407 return d_categoryManager.defaultCategory();
2408}
2409
2410inline
2411const Category *LoggerManager::setCategory(const char *categoryName)
2412{
2413 BSLS_ASSERT(categoryName);
2414 return d_categoryManager.setCategory(categoryName);
2415}
2416
2417inline
2419 const char *categoryName)
2420{
2421 BSLS_ASSERT(categoryName);
2422 return d_categoryManager.setCategory(categoryHolder, categoryName);
2423}
2424
2425inline
2426Category *LoggerManager::setCategory(const char *categoryName,
2427 int recordLevel,
2428 int passLevel,
2429 int triggerLevel,
2430 int triggerAllLevel)
2431{
2432 BSLS_ASSERT(categoryName);
2433 return d_categoryManager.setCategory(categoryName,
2434 recordLevel,
2435 passLevel,
2436 triggerLevel,
2437 triggerAllLevel);
2438}
2439
2440inline
2442{
2443 BSLS_ASSERT(0 <= length);
2444 d_categoryManager.setMaxNumCategories(length);
2445}
2446
2447inline
2449{
2450 BSLS_ASSERT(category);
2451 d_categoryManager.setCategoryThresholdsToCurrentDefaults(category);
2452}
2453
2454inline
2456{
2457 BSLS_ASSERT(category);
2458 d_categoryManager.setCategoryThresholdsToFactoryDefaults(category);
2459}
2460
2461 // Category Management
2462
2463inline
2464Category *LoggerManager::addCategory(const char *categoryName,
2465 int recordLevel,
2466 int passLevel,
2467 int triggerLevel,
2468 int triggerAllLevel)
2469{
2470 BSLS_ASSERT(categoryName);
2471 return d_categoryManager.addCategory(categoryName,
2472 recordLevel,
2473 passLevel,
2474 triggerLevel,
2475 triggerAllLevel);
2476}
2477
2478inline
2479Category *LoggerManager::lookupCategory(const char *categoryName)
2480{
2481 BSLS_ASSERT(categoryName);
2482 return d_categoryManager.lookupCategory(categoryName);
2483}
2484
2485 // Threshold Level Management
2486
2487inline
2489 int passLevel,
2490 int triggerLevel,
2491 int triggerAllLevel)
2492{
2493 return d_categoryManager.setDefaultThresholdLevels(recordLevel,
2494 passLevel,
2495 triggerLevel,
2496 triggerAllLevel);
2497}
2498
2499inline
2505
2506inline
2508 const char *categoryNamePrefix,
2509 int recordLevel,
2510 int passLevel,
2511 int triggerLevel,
2512 int triggerAllLevel)
2513{
2514 BSLS_ASSERT(categoryNamePrefix);
2515 return d_categoryManager.setThresholdLevelsHierarchically(
2516 categoryNamePrefix,
2517 recordLevel,
2518 passLevel,
2519 triggerLevel,
2520 triggerAllLevel);
2521}
2522
2523inline
2525{
2526 return d_categoryManager.defaultThresholdLevels();
2527}
2528
2529inline
2530const Category *LoggerManager::lookupCategory(const char *categoryName) const
2531{
2532 BSLS_ASSERT(categoryName);
2533 return d_categoryManager.lookupCategory(categoryName);
2534}
2535
2536inline
2538 ThresholdAggregate *levels,
2539 const char *categoryName) const
2540{
2541 BSLS_ASSERT(levels);
2542 BSLS_ASSERT(categoryName);
2543 return d_categoryManager.thresholdLevelsForNewCategory(levels,
2544 categoryName);
2545}
2546
2547 // Observer Management
2548
2549inline
2551{
2552 d_observer->deregisterAllObservers();
2553}
2554
2555inline
2557{
2558 return d_observer->deregisterObserver(observerName);
2559}
2560
2561inline
2563 const bsl::string_view& collectorName)
2564{
2565 return d_attributeCollectors.removeCollector(collectorName);
2566}
2567
2568inline
2571{
2572 return d_observer->findObserver(observerName);
2573}
2574
2575template <class t_OBSERVER>
2576inline
2578 const bsl::string_view& observerName)
2579{
2580 return d_observer->findObserver(result, observerName);
2581}
2582
2583inline
2584int
2586 const bsl::string_view& observerName)
2587{
2588 return d_observer->registerObserver(observer, observerName);
2589}
2590
2591inline
2592int
2594 const AttributeCollector& collector,
2595 const bsl::string_view& collectorName)
2596{
2597 return d_attributeCollectors.addCollector(collector, collectorName);
2598}
2599 // Threshold Level Management
2600
2601inline
2606
2607 // Rule Management
2608
2609inline
2611{
2612 return d_categoryManager.addRule(value);
2613}
2614
2615inline
2617{
2618 return d_categoryManager.addRules(ruleSet);
2619}
2620
2621inline
2623{
2624 d_categoryManager.removeAllRules();
2625}
2626
2627inline
2629{
2630 return d_categoryManager.removeRule(value);
2631}
2632
2633inline
2635{
2636 return d_categoryManager.removeRules(ruleSet);
2637}
2638
2639 // Miscellaneous
2640
2641inline
2646
2647template <class t_CATEGORY_VISITOR>
2648inline
2649void LoggerManager::visitCategories(const t_CATEGORY_VISITOR& visitor)
2650{
2651 d_categoryManager.visitCategories(visitor);
2652}
2653
2654template <class t_OBSERVER_VISITOR>
2655inline
2657 BSLS_COMPILERFEATURES_FORWARD_REF(t_OBSERVER_VISITOR) visitor)
2658{
2659 d_observer->visitObservers(
2660 BSLS_COMPILERFEATURES_FORWARD(t_OBSERVER_VISITOR, visitor));
2661}
2662
2663inline
2665{
2667 d_defaultLoggerCount.loadAcquire())) {
2668 return getLoggerSlow();
2669 }
2670 return *d_logger_p;
2671}
2672
2673// ACCESSORS
2674inline
2676{
2677 return d_allocator_p;
2678}
2679
2680inline
2682{
2683 return d_categoryManager.defaultCategory();
2684}
2685
2686inline
2688{
2689 return d_categoryManager.defaultPassThresholdLevel();
2690}
2691
2692inline
2694{
2695 return d_categoryManager.defaultRecordThresholdLevel();
2696}
2697
2698inline
2700{
2701 return d_categoryManager.defaultTriggerAllThresholdLevel();
2702}
2703
2704inline
2706{
2707 return d_categoryManager.defaultTriggerThresholdLevel();
2708}
2709
2710inline
2713{
2714 const BroadcastObserver *observerPtr = d_observer.get();
2715
2716 return observerPtr->findObserver(observerName);
2717}
2718
2719template <class t_OBSERVER>
2720inline
2723 const bsl::string_view& observerName) const
2724{
2725 const BroadcastObserver *observerPtr = d_observer.get();
2726
2727 return observerPtr->findObserver(result, observerName);
2728}
2729
2730inline
2732{
2733 return d_categoryManager.maxNumCategories();
2734}
2735
2736inline
2738{
2739 return d_categoryManager.length();
2740}
2741
2742inline
2744{
2745 return d_categoryManager.ruleSet();
2746}
2747
2748template <class t_CATEGORY_VISITOR>
2749inline
2750void LoggerManager::visitCategories(const t_CATEGORY_VISITOR& visitor) const
2751{
2752 d_categoryManager.visitCategories(visitor);
2753}
2754
2755template <class t_OBSERVER_VISITOR>
2756inline
2758 BSLS_COMPILERFEATURES_FORWARD_REF(t_OBSERVER_VISITOR) visitor) const
2759{
2760 d_observer->visitObservers(
2761 BSLS_COMPILERFEATURES_FORWARD(t_OBSERVER_VISITOR, visitor));
2762}
2763
2764 // ------------------------------
2765 // class LoggerManagerScopedGuard
2766 // ------------------------------
2767
2768// CREATORS
2769#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2770inline
2771LoggerManagerScopedGuard::LoggerManagerScopedGuard(
2772 Observer *observer,
2773 const LoggerManagerConfiguration& configuration,
2774 bslma::Allocator *globalAllocator)
2775{
2776 LoggerManager::initSingleton(observer, configuration, globalAllocator);
2777}
2778#endif // BDE_OMIT_INTERNAL_DEPRECATED
2779
2780inline
2781LoggerManagerScopedGuard::LoggerManagerScopedGuard(
2782 const LoggerManagerConfiguration& configuration,
2783 bslma::Allocator *globalAllocator)
2784{
2785 LoggerManager::initSingleton(configuration, globalAllocator);
2786}
2787
2788inline
2793
2794#ifndef BDE_OMIT_INTERNAL_DEPRECATED
2795
2796 // -------------------------------
2797 // class LoggerManagerCategoryIter
2798 // -------------------------------
2799
2800// CREATORS
2801inline
2802LoggerManagerCategoryIter::LoggerManagerCategoryIter(
2803 const LoggerManager& loggerManager)
2804: d_iter(loggerManager.d_categoryManager)
2805{
2806}
2807
2808// MANIPULATORS
2809inline
2811{
2812 ++d_iter;
2813}
2814
2815// ACCESSORS
2816inline
2817LoggerManagerCategoryIter::operator const void *() const
2818{
2819 return d_iter;
2820}
2821
2822inline
2824{
2825 return d_iter();
2826}
2827
2828 // --------------------------------
2829 // class LoggerManagerCategoryManip
2830 // --------------------------------
2831
2832// CREATORS
2833inline
2834LoggerManagerCategoryManip::LoggerManagerCategoryManip(
2835 LoggerManager *loggerManager)
2836: d_manip(&loggerManager->d_categoryManager)
2837{
2838 BSLS_ASSERT(loggerManager);
2839}
2840
2841// MANIPULATORS
2842inline
2844{
2845 d_manip.advance();
2846}
2847
2848inline
2850{
2851 return d_manip();
2852}
2853
2854// ACCESSORS
2855inline
2856LoggerManagerCategoryManip::operator const void *() const
2857{
2858 return d_manip;
2859}
2860
2861#endif // BDE_OMIT_INTERNAL_DEPRECATED
2862
2863} // close package namespace
2864
2865
2866#endif
2867
2868// ----------------------------------------------------------------------------
2869// Copyright 2017 Bloomberg Finance L.P.
2870//
2871// Licensed under the Apache License, Version 2.0 (the "License");
2872// you may not use this file except in compliance with the License.
2873// You may obtain a copy of the License at
2874//
2875// http://www.apache.org/licenses/LICENSE-2.0
2876//
2877// Unless required by applicable law or agreed to in writing, software
2878// distributed under the License is distributed on an "AS IS" BASIS,
2879// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2880// See the License for the specific language governing permissions and
2881// limitations under the License.
2882// ----------------------------- END-OF-FILE ----------------------------------
2883
2884/** @} */
2885/** @} */
2886/** @} */
Definition ball_attributecollectorregistry.h:182
int addCollector(const Collector &collector, const bsl::string_view &name)
bsl::function< void(const ball::Attribute &)> Visitor
Visitor is the type of a user-supplied visit functor.
Definition ball_attributecollectorregistry.h:188
int removeCollector(const bsl::string_view &name)
Definition ball_broadcastobserver.h:226
bsl::shared_ptr< Observer > findObserver(const bsl::string_view &observerName)
Definition ball_category.h:367
Definition ball_categorymanager.h:1086
Definition ball_categorymanager.h:1147
void advance()
Definition ball_categorymanager.h:1367
Definition ball_categorymanager.h:426
void setMaxNumCategories(int length)
Definition ball_categorymanager.h:1250
Category * lookupCategory(const char *categoryName)
void setCategoryThresholdsToCurrentDefaults(Category *category) const
Category * addCategory(const char *categoryName, int recordLevel, int passLevel, int triggerLevel, int triggerAllLevel)
Definition ball_categorymanager.h:1215
const RuleSet & ruleSet() const
Definition ball_categorymanager.h:1296
int addRule(const Rule &ruleToAdd)
int addRules(const RuleSet &ruleSet)
int defaultRecordThresholdLevel() const
Return the default record threshold level of this object.
int removeRules(const RuleSet &ruleSet)
int maxNumCategories() const
Definition ball_categorymanager.h:1289
int setThresholdLevelsHierarchically(const char *categoryNamePrefix, int recordLevel, int passLevel, int triggerLevel, int triggerAllLevel)
int removeRule(const Rule &ruleToRemove)
int defaultTriggerThresholdLevel() const
Return the default trigger threshold level of this object.
int defaultTriggerAllThresholdLevel() const
Return the default trigger-all threshold level of this object.
ThresholdAggregate defaultThresholdLevels() const
Return the default threshold levels associated with this object.
Category * addCategoryHierarchically(const char *categoryName)
int length() const
Definition ball_categorymanager.h:1282
Category & defaultCategory()
Definition ball_categorymanager.h:1232
void setCategoryThresholdsToFactoryDefaults(Category *category) const
int setDefaultThresholdLevels(int recordLevel, int passLevel, int triggerLevel, int triggerAllLevel)
int defaultPassThresholdLevel() const
Return the default pass threshold level of this object.
void visitCategories(const t_CATEGORY_VISITOR &visitor)
Definition ball_categorymanager.h:1257
void setDefaultThresholdLevelsCallback(const DefaultThresholdLevelsCallback *defaultThresholdLevelsCallback)
void resetDefaultThresholdLevels()
int thresholdLevelsForNewCategory(ThresholdAggregate *levels, const char *categoryName) const
const Category * setCategory(const char *categoryName)
Definition ball_categorymanager.h:1244
Definition ball_category.h:184
Definition ball_context.h:297
Definition ball_loggermanager.h:2226
const Category & operator()() const
Definition ball_loggermanager.h:2823
void operator++()
Definition ball_loggermanager.h:2810
Definition ball_loggermanager.h:2285
Category & operator()()
Definition ball_loggermanager.h:2849
void advance()
Definition ball_loggermanager.h:2843
Definition ball_loggermanagerconfiguration.h:283
TriggerMarkers
Definition ball_loggermanagerconfiguration.h:327
LogOrder
Definition ball_loggermanagerconfiguration.h:304
Definition ball_loggermanager.h:2162
~LoggerManagerScopedGuard()
Definition ball_loggermanager.h:2789
Definition ball_loggermanager.h:1293
static LoggerManager & initSingleton(Observer *observer, const LoggerManagerConfiguration &configuration, bslma::Allocator *globalAllocator=0)
int defaultPassThresholdLevel() const
Return the default pass threshold level of this logger manager.
Definition ball_loggermanager.h:2687
int addRules(const RuleSet &ruleSet)
Definition ball_loggermanager.h:2616
BroadcastObserver::ObserverRegistry ObserverRegistry
Definition ball_loggermanager.h:1330
int defaultTriggerThresholdLevel() const
Return the default trigger threshold level of this logger manager.
Definition ball_loggermanager.h:2705
Category * addCategoryHierarchically(const char *categoryName)
Definition ball_loggermanager.h:2398
int defaultTriggerAllThresholdLevel() const
Definition ball_loggermanager.h:2699
int numCategories() const
Definition ball_loggermanager.h:2737
bool isCategoryEnabled(const Category *category, int severity) const
bsl::shared_ptr< Observer > findObserver(const bsl::string_view &observerName)
Definition ball_loggermanager.h:2570
CategoryCallbacks::DefaultThresholdLevels DefaultThresholdLevelsCallback
Definition ball_loggermanager.h:1306
int deregisterObserver(const bsl::string_view &observerName)
Definition ball_loggermanager.h:2556
int defaultRecordThresholdLevel() const
Return the default record threshold level of this logger manager.
Definition ball_loggermanager.h:2693
LoggerManagerConfiguration::UserFieldsPopulatorCallback UserFieldsPopulatorCallback
Definition ball_loggermanager.h:1318
bslma::Allocator * allocator() const
Definition ball_loggermanager.h:2675
AttributeCollectorRegistry::Visitor AttributeVisitor
Definition ball_loggermanager.h:1326
int registerAttributeCollector(const AttributeCollector &collector, const bsl::string_view &collectorName)
Definition ball_loggermanager.h:2593
Logger * allocateLogger(RecordBuffer *buffer, int scratchBufferSize, Observer *observer)
~LoggerManager()
Destroy this logger manager.
const Category * setCategory(const char *categoryName)
Definition ball_loggermanager.h:2411
void setDefaultThresholdLevelsCallback(DefaultThresholdLevelsCallback *callback)
Definition ball_loggermanager.h:2500
void removeAllRules()
Remove every rule from the set of rules maintained by this object.
Definition ball_loggermanager.h:2622
int thresholdLevelsForNewCategory(ThresholdAggregate *levels, const char *categoryName) const
Definition ball_loggermanager.h:2537
Observer * observer()
static char * obtainMessageBuffer(bslmt::Mutex **mutex, int *bufferSize)
void publishAll()
Definition ball_loggermanager.h:2642
static LoggerManager & initSingleton(Observer *observer, bslma::Allocator *globalAllocator=0)
int setDefaultThresholdLevels(int recordLevel, int passLevel, int triggerLevel, int triggerAllLevel)
Definition ball_loggermanager.h:2488
const UserFieldsPopulatorCallback * userFieldsPopulatorCallback() const
void deregisterAllObservers()
Definition ball_loggermanager.h:2550
Logger * allocateLogger(RecordBuffer *buffer, int scratchBufferSize)
ThresholdAggregate defaultThresholdLevels() const
Definition ball_loggermanager.h:2524
void resetDefaultThresholdLevels()
Definition ball_loggermanager.h:2602
void visitCategories(const t_CATEGORY_VISITOR &visitor)
Definition ball_loggermanager.h:2649
void setMaxNumCategories(int length)
Definition ball_loggermanager.h:2441
Logger * allocateLogger(RecordBuffer *buffer)
Category * addCategory(const char *categoryName, int recordLevel, int passLevel, int triggerLevel, int triggerAllLevel)
Definition ball_loggermanager.h:2464
void visitObservers(BSLS_COMPILERFEATURES_FORWARD_REF(t_OBSERVER_VISITOR) visitor)
Definition ball_loggermanager.h:2656
int removeRule(const Rule &value)
Definition ball_loggermanager.h:2628
int addRule(const Rule &value)
Definition ball_loggermanager.h:2610
static void logMessage(int severity, Record *record)
void setCategoryThresholdsToFactoryDefaults(Category *category)
Definition ball_loggermanager.h:2455
static LoggerManager & singleton()
Definition ball_loggermanager.h:2389
static int initSingleton(LoggerManager *singleton, bool adoptSingleton=false)
int deregisterAttributeCollector(const bsl::string_view &collectorName)
Definition ball_loggermanager.h:2562
Logger & getLogger()
Definition ball_loggermanager.h:2664
static Record * getRecord(const bsl::string_view &fileName, int lineNumber)
AttributeCollectorRegistry::Collector AttributeCollector
Definition ball_loggermanager.h:1322
Logger * allocateLogger(RecordBuffer *buffer, const bsl::shared_ptr< Observer > &observer)
Category * lookupCategory(const char *categoryName)
Definition ball_loggermanager.h:2479
int setThresholdLevelsHierarchically(const char *categoryNamePrefix, int recordLevel, int passLevel, int triggerLevel, int triggerAllLevel)
Definition ball_loggermanager.h:2507
int registerObserver(const bsl::shared_ptr< Observer > &observer, const bsl::string_view &observerName)
Definition ball_loggermanager.h:2585
int maxNumCategories() const
Definition ball_loggermanager.h:2731
void setLogger(Logger *logger)
Logger * allocateLogger(RecordBuffer *buffer, Observer *observer)
int removeRules(const RuleSet &ruleSet)
Definition ball_loggermanager.h:2634
static LoggerManager & initSingleton(const LoggerManagerConfiguration &configuration, bslma::Allocator *globalAllocator=0)
Logger * allocateLogger(RecordBuffer *buffer, int scratchBufferSize, const bsl::shared_ptr< Observer > &observer)
static bool isInitialized()
Definition ball_loggermanager.h:2383
static void createLoggerManager(bslma::ManagedPtr< LoggerManager > *manager, Observer *observer, const LoggerManagerConfiguration &configuration, bslma::Allocator *basicAllocator=0)
Category & defaultCategory()
Definition ball_loggermanager.h:2405
static bslma::ManagedPtr< char > obtainMessageBuffer(int *bufferSize)
const Observer * observer() const
static void shutDownSingleton()
LoggerManager(const LoggerManagerConfiguration &configuration, bslma::Allocator *globalAllocator=0)
void setCategoryThresholdsToCurrentDefaults(Category *category)
Definition ball_loggermanager.h:2448
static LoggerManager & initSingleton(bslma::Allocator *globalAllocator=0)
Logger::PublishAllTriggerCallback PublishAllTriggerCallback
Definition ball_loggermanager.h:1312
static void createLoggerManager(bslma::ManagedPtr< LoggerManager > *manager, const LoggerManagerConfiguration &configuration, bslma::Allocator *basicAllocator=0)
CategoryCallbacks::NameFilter CategoryNameFilterCallback
Definition ball_loggermanager.h:1300
void deallocateLogger(Logger *logger)
const RuleSet & ruleSet() const
Definition ball_loggermanager.h:2743
Definition ball_loggermanager.h:1010
int numRecordsInUse() const
Definition ball_loggermanager.h:2372
void logMessage(const Category &category, int severity, Record *record)
LoggerManagerConfiguration::UserFieldsPopulatorCallback UserFieldsPopulatorCallback
Definition ball_loggermanager.h:1019
void removeAll()
Remove all log records from the record buffer of this logger.
Definition ball_loggermanager.h:2359
bsl::function< void(Transmission::Cause)> PublishAllTriggerCallback
Definition ball_loggermanager.h:1024
void logMessage(const Category &category, int severity, const bsl::string_view &fileName, int lineNumber, const bsl::string_view &message)
char * obtainMessageBuffer(bslmt::Mutex **mutex, int *bufferSize)
char * messageBuffer()
Definition ball_loggermanager.h:2346
void publish()
Definition ball_loggermanager.h:2353
int messageBufferSize() const
Definition ball_loggermanager.h:2366
Record * getRecord(const bsl::string_view &fileName, int lineNumber)
bslma::ManagedPtr< char > obtainMessageBuffer(int *bufferSize)
Definition ball_observer.h:235
Definition ball_recordbuffer.h:288
virtual void removeAll()=0
Definition ball_record.h:176
Definition ball_ruleset.h:151
Definition ball_rule.h:177
Definition ball_thresholdaggregate.h:101
Definition bdlcc_objectpool.h:462
Definition bdlcc_sharedobjectpool.h:369
Definition bdlma_concurrentpool.h:332
Definition bslstl_stringview.h:471
Definition bslstl_map.h:653
Definition bslstl_set.h:691
Definition bslstl_sharedptr.h:1838
element_type * get() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_sharedptr.h:5665
Definition bslma_allocator.h:545
Definition bslma_managedptr.h:1173
Definition bslmt_mutex.h:317
Definition bslmt_readerwritermutex.h:244
Definition bsls_atomic.h:1050
unsigned int loadAcquire() const
Definition bsls_atomic.h:2100
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
Definition ball_administration.h:214
bsl::function< void(bsl::string *buffer, const char *categoryName)> NameFilter
Definition ball_categorycallbacks.h:173
Cause
Definition ball_transmission.h:215
@ e_MANUAL_PUBLISH
Definition ball_transmission.h:219
@ e_MANUAL_PUBLISH_ALL
Definition ball_transmission.h:220
bsl::function< void(void *, bslma::Allocator *)> DefaultCreator
Definition bdlcc_objectpool.h:421