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