BDE 4.14.0 Production release
Loading...
Searching...
No Matches

Macros

#define BALL_LOG_CATEGORY    (ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER)->category())
 
#define BALL_LOG_THRESHOLD    (ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER)->threshold())
 
#define BALL_LOG_RECORD   (ball_log_lOg_StReAm.record())
 
#define BALL_LOG_OUTPUT_STREAM   (ball_log_lOg_StReAm.stream())
 
#define BALL_LOG_SET_CATEGORY(CATEGORY)
 
#define BALL_LOG_SET_CATEGORY_HIERARCHICALLY(CATEGORY)
 
#define BALL_LOG_SET_DYNAMIC_CATEGORY(CATEGORY)
 
#define BALL_LOG_SET_DYNAMIC_CATEGORY_HIERARCHICALLY(CATEGORY)
 
#define BALL_LOG_SET_CLASS_CATEGORY(CATEGORY)
 
#define BALL_LOG_SET_CLASS_CATEGORY_HIERARCHICALLY(CATEGORY)
 
#define BALL_LOG_SET_NAMESPACE_CATEGORY(CATEGORY)
 
#define BALL_LOG_SET_NAMESPACE_CATEGORY_HIERARCHICALLY(CATEGORY)
 
#define BALL_LOG_STREAM_CONST_IMP(SEVERITY)
 
#define BALL_LOG_STREAM_IMP(SEVERITY)
 
#define BALL_LOG_STREAM(SEVERITY)    BALL_LOG_STREAM_IMP((SEVERITY)) BALL_LOG_OUTPUT_STREAM
 
#define BALL_LOG_TRACE
 
#define BALL_LOG_DEBUG
 
#define BALL_LOG_INFO
 
#define BALL_LOG_WARN
 
#define BALL_LOG_ERROR
 
#define BALL_LOG_FATAL
 
#define BALL_LOG_STREAM_BLOCK(SEVERITY)   BALL_LOG_STREAM_IMP((SEVERITY))
 
#define BALL_LOG_TRACE_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_TRACE)
 
#define BALL_LOG_DEBUG_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_DEBUG)
 
#define BALL_LOG_INFO_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_INFO)
 
#define BALL_LOG_WARN_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_WARN)
 
#define BALL_LOG_ERROR_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_ERROR)
 
#define BALL_LOG_FATAL_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_FATAL)
 
#define BALL_LOG_END   ""
 
#define BALL_LOGCB_STREAM_CONST_IMP(SEVERITY, CALLBACK)
 
#define BALL_LOGCB_STREAM_IMP(SEVERITY, CALLBACK)
 
#define BALL_LOGCB_STREAM(BALL_SEVERITY, CALLBACK)    BALL_LOGCB_STREAM_IMP((BALL_SEVERITY), (CALLBACK)) BALL_LOG_OUTPUT_STREAM
 
#define BALL_LOGCB_TRACE(CALLBACK)
 
#define BALL_LOGCB_DEBUG(CALLBACK)
 
#define BALL_LOGCB_INFO(CALLBACK)
 
#define BALL_LOGCB_WARN(CALLBACK)
 
#define BALL_LOGCB_ERROR(CALLBACK)
 
#define BALL_LOGCB_FATAL(CALLBACK)
 
#define BALL_LOGCB_STREAM_BLOCK(BALL_SEVERITY, CALLBACK)    BALL_LOGCB_STREAM_IMP((BALL_SEVERITY), (CALLBACK))
 
#define BALL_LOGCB_TRACE_BLOCK(CALLBACK)
 
#define BALL_LOGCB_DEBUG_BLOCK(CALLBACK)
 
#define BALL_LOGCB_INFO_BLOCK(CALLBACK)
 
#define BALL_LOGCB_WARN_BLOCK(CALLBACK)
 
#define BALL_LOGCB_ERROR_BLOCK(CALLBACK)
 
#define BALL_LOGCB_FATAL_BLOCK(CALLBACK)
 
#define BALL_LOGCB_END   ""
 
#define BALL_LOGVA_CONST_IMP(SEVERITY, ...)
 
#define BALL_LOGVA(SEVERITY, ...)
 
#define BALL_LOGVA_TRACE(...)    BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_TRACE, __VA_ARGS__)
 
#define BALL_LOGVA_DEBUG(...)    BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_DEBUG, __VA_ARGS__)
 
#define BALL_LOGVA_INFO(...)    BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_INFO, __VA_ARGS__)
 
#define BALL_LOGVA_WARN(...)    BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_WARN, __VA_ARGS__)
 
#define BALL_LOGVA_ERROR(...)    BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_ERROR, __VA_ARGS__)
 
#define BALL_LOGVA_FATAL(...)    BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_FATAL, __VA_ARGS__)
 
#define BALL_LOG_IS_ENABLED(SEVERITY)
 

Detailed Description

Outline

Purpose

Provide macros and utility functions to facilitate logging.

Classes

Macros

See also
ball_loggermanager, ball_category, ball_severity, ball_record

Description

This component provides preprocessor macros and utility functions to facilitate use of the ball_loggermanager component. In particular, the macros defined herein greatly simplify the mechanics of generating log records. The utility functions provided in ball::Log are intended only for use by the macros and should not be called directly.

The macros defined herein pertain to the logger manager singleton only, and not to any non-singleton instances of ball::LoggerManager. In particular, the macros do not have any effect unless the logger manager singleton is initialized. Note that the flow of control may pass through a use of any of the macros before the logger manager singleton has been initialized or after it has been destroyed; however, control should not pass through any macro use during logger manager singleton initialization or destruction. See {ball_loggermanager |Logger Manager Singleton Initialization} for details on the recommended procedure for initializing the singleton.

Thread Safety

All macros defined in this component are thread-safe, and can be invoked concurrently by multiple threads.

Additionally, each use of a logging macro will create a distinct log record, and ball::Observer implementations (like those in ball) generally guarantee that output for different log records are not interleaved.

Macro Reference

This section documents the preprocessor macros defined in this component.

The first three macros described below are used to define categories, at either block scope or class scope, to which records are logged by the C++ stream-based and printf-style logging macros (described further below).

Macros for Defining Categories at Block Scope

The following two macros are used to establish logging categories that have block scope:

BALL_LOG_SET_CATEGORY(CATEGORY): Set a category for logging to the specified CATEGORY (assumed to be of type convertible to const char *). On the first invocation of this macro in a code block, the ball::Log::setCategory method is invoked to retrieve the address of an appropriate category structure for its scope; subsequent invocations will use a cached address of the category. (See the function-level documentation of ball::Log::setCategory for more information.) This macro must be used at block scope, and can be used at most once in any given block (or else a compiler diagnostic will result).

BALL_LOG_SET_DYNAMIC_CATEGORY(CATEGORY): Set, on EACH invocation, a category for logging to the specified CATEGORY (assumed to be of type convertible to const char *). On EVERY invocation of this macro in a code block, the ball::Log::setCategory method is invoked to retrieve the address of an appropriate category structure for its scope; the address returned from ball::Log::setCategory is NOT cached for subsequent calls. (See the function-level documentation of ball::Log::setCategory for more information.) This macro must be used at block scope and can be used at most once in any given block (or else a compiler diagnostic will result). Note that this macro should be used to create categories that depend on RUN-TIME values only (e.g., LUW or UUID).

There can be at most one use of either BALL_LOG_SET_CATEGORY or BALL_LOG_SET_DYNAMIC_CATEGORY in any given block (or else a compiler diagnostic will result). Note that categories that are set using these macros, including dynamic categories, are not destroyed until the logger manager singleton is destroyed.

Macro for Defining Categories at Class Scope

The following macro is used to establish logging categories that have class scope:

BALL_LOG_SET_CLASS_CATEGORY(CATEGORY): Set a category for logging to the specified CATEGORY (assumed to be of type convertible to const char *) in the scope of the class within which this macro is used. Similar to BALL_LOG_SET_CATEGORY, the category is set once only, the first time that it is accessed (i.e., it is not a dynamic category). This macro must be used, at most once, within the definition of a class or class template (or else a compiler diagnostic will result). Note that use of this macro may occur in either a public, private, or protected section of a class's interface, although private should be preferred.

Note that similar to block-scope categories (see BALL_LOG_SET_CATEGORY and BALL_LOG_SET_DYNAMIC_CATEGORY), class-scope categories are not destroyed until the logger manager singleton is destroyed.

Macro for Defining Categories at Namespace or Global Scope

The following macro is used to establish logging categories that have namespace or global scope:

BALL_LOG_SET_NAMESPACE_CATEGORY(CATEGORY): Set a category for logging to the specified CATEGORY (assumed to be of type convertible to const char *) in the namespace (or global) scope within which this macro is used. Similar to BALL_LOG_SET_CATEGORY, the category is set once only, the first time that it is accessed (i.e., it is not a dynamic category). This macro may be used, in .cpp files only, at most once in any given namespace and at most once at global scope (or else a compiler diagnostic will result). Do NOT use this macro in .h files.

Note that similar to block-scope categories (see BALL_LOG_SET_CATEGORY and BALL_LOG_SET_DYNAMIC_CATEGORY), namespace-scope categories are not destroyed until the logger manager singleton is destroyed.

Macros for Defining Hierarchical Categories

The following macros are used to establish logging categories having thresholds that are given by the existing non-default category whose name matches the longest prefix of the new category's name (i.e., the threshold levels of new categories are determined "hierarchically" from existing categories rather than from the default threshold levels of the logger manager singleton).

BALL_LOG_SET_CATEGORY_HIERARCHICALLY(CATEGORY) Set a category for logging to the specified CATEGORY (assumed to be of type convertible to const char *). On the first invocation of this macro in a code block, the ball::Log::setCategoryHierarchically method is invoked to retrieve the address of an appropriate category structure for its scope; subsequent invocations will use a cached address of the category. (See the function-level documentation of ball::Log::setCategoryHierarchically for more information.) This macro must be used at block scope, and can be used at most once in any given block (or else a compiler diagnostic will result).

BALL_LOG_SET_DYNAMIC_CATEGORY_HIERARCHICALLY(CATEGORY): Set, on EACH invocation, a category for logging to the specified CATEGORY (assumed to be of type convertible to const char *). On EVERY invocation of this macro in a code block, the ball::Log::setCategoryHierarchically method is invoked to retrieve the address of an appropriate category structure for its scope; the address returned from ball::Log::setCategoryHierarchically is NOT cached for subsequent calls. (See the function-level documentation of ball::Log::setCategoryHierarchically for more information.) This macro must be used at block scope and can be used at most once in any given block (or else a compiler diagnostic will result). Note that this macro should be used to create categories that depend on RUN-TIME values only (e.g., LUW or UUID).

BALL_LOG_SET_CLASS_CATEGORY_HIERARCHICALLY(CATEGORY) Set a category for logging to the specified CATEGORY (assumed to be of type convertible to const char *) in the scope of the class within which this macro is used. Similar to BALL_LOG_SET_CATEGORY_HIERARCHICALLY, the category is set once only, using the ball::Log::setCategoryHierarchically function, the first time that it is accessed (i.e., it is not a dynamic category). (See the function-level documentation for ball::Log::setCategoryHierarchically for more information.) This macro must be used, at most once, within the definition of a class or class template (or else a compiler diagnostic will result). Note that use of this macro may occur in either a public, private, or protected section of a class's interface, although private should be preferred.

BALL_LOG_SET_NAMESPACE_CATEGORY_HIERARCHICALLY(CATEGORY) Set a category for logging to the specified CATEGORY (assumed to be of type convertible to const char *) in the namespace (or global) scope within which this macro is used. Similar to BALL_LOG_SET_CATEGORY_HIERARCHICALLY, the category is set once only, using the ball::Log::setCategoryHierarchically function, the first time that it is accessed (i.e., it is not a dynamic category). (See the function-level documentation for ball::Log::setCategoryHierarchically for more information.) This macro may be used, in .cpp files only, at most once in any given namespace and at most once at global scope (or else a compiler diagnostic will result). Do NOT use this macro in .h files.

Macros for Logging Records

The macros defined in this subsection are the ones that are actually used to produce log records. A use of any one of the logging macros requires that a logging category (as established by the macros defined above) be in scope at the point where the macro is used. Note that the formatted string that is generated for the message attribute of each log record includes the category that is in scope and the filename as established by the standard __FILE__ macro.

The code within any logging statement/code block must not produce any side effects because it may or may not be executed based on run-time configuration of the ball logging subsystem:

BALL_LOG_INFO << ++i; // (!) May or may not be incremented
processRequest(...); // (!) May or may not be called
}
#define BALL_LOG_TRACE_BLOCK
Definition ball_log.h:1247
#define BALL_LOG_INFO
Definition ball_log.h:1229

A set of macros based on C++ streams, BALL_LOG_TRACE, BALL_LOG_DEBUG, BALL_LOG_INFO, BALL_LOG_WARN, BALL_LOG_ERROR, and BALL_LOG_FATAL, are the ones most commonly used for logging. They have the following usage pattern:

BALL_LOG_TRACE << X << Y ... ;
BALL_LOG_DEBUG << X << Y ... ;
BALL_LOG_INFO << X << Y ... ;
BALL_LOG_WARN << X << Y ... ;
BALL_LOG_ERROR << X << Y ... ;
BALL_LOG_FATAL << X << Y ... ;
where X, Y, ... represents any sequence of values for which
`operator<<` is defined. The resulting formatted message string is
logged with the severity indicated by the name of the macro
(e.g., `BALL_LOG_TRACE` logs with severity `ball::Severity::e_TRACE`).
#define BALL_LOG_DEBUG
Definition ball_log.h:1225
#define BALL_LOG_FATAL
Definition ball_log.h:1241
#define BALL_LOG_ERROR
Definition ball_log.h:1237
#define BALL_LOG_WARN
Definition ball_log.h:1233
#define BALL_LOG_TRACE
Definition ball_log.h:1221
@ e_TRACE
Definition ball_severity.h:174

A closely-related macro also based on C++ streams, BALL_LOG_STREAM, requires that the severity be explicitly supplied as an argument:

BALL_LOG_STREAM(SEVERITY) << X << Y ... ;
where X, Y, ... represents any sequence of values for which
`operator<<` is defined. The resulting formatted message string is
logged with the specified `SEVERITY`.
#define BALL_LOG_STREAM(SEVERITY)
Definition ball_log.h:1218

Another set of macros based on C++ streams, similar to BALL_LOG_TRACE, etc., allow the caller to specify a "callback" function that is passed the ball::UserFields * used to represent the user fields of a log record. BALL_LOGCB_TRACE, BALL_LOGCB_DEBUG, BALL_LOGCB_INFO, BALL_LOGCB_WARN, BALL_LOGCB_ERROR, and BALL_LOGCB_FATAL have the following usage pattern:

BALL_LOGCB_TRACE(CALLBACK) << X << Y ... ;
BALL_LOGCB_DEBUG(CALLBACK) << X << Y ... ;
BALL_LOGCB_INFO(CALLBACK) << X << Y ... ;
BALL_LOGCB_WARN(CALLBACK) << X << Y ... ;
BALL_LOGCB_ERROR(CALLBACK) << X << Y ... ;
BALL_LOGCB_FATAL(CALLBACK) << X << Y ... ;
where X, Y, ... represents any sequence of values for which
`operator<<` is defined and `CALLBACK` is a callback taking a
`ball::UserFields *` as an argument. The resulting formatted message
string is logged with the severity indicated by the name of the macro
(e.g., `BALL_LOGCB_ERROR` logs with severity
`ball::Severity::e_ERROR`). The generated log record will contain the
`ball::UserFields` representing user fields as populated by `CALLBACK`.
Note that the callback supplied to the logging macro must match the
prototype `void (*)(ball::UserFields *)`.
Definition ball_userfields.h:136
#define BALL_LOGCB_FATAL(CALLBACK)
Definition ball_log.h:1341
#define BALL_LOGCB_ERROR(CALLBACK)
Definition ball_log.h:1336
#define BALL_LOGCB_TRACE(CALLBACK)
Definition ball_log.h:1316
#define BALL_LOGCB_INFO(CALLBACK)
Definition ball_log.h:1326
#define BALL_LOGCB_WARN(CALLBACK)
Definition ball_log.h:1331
#define BALL_LOGCB_DEBUG(CALLBACK)
Definition ball_log.h:1321
@ e_ERROR
Definition ball_severity.h:170

A closely-related macro also based on C++ streams, BALL_LOGCB_STREAM, requires that the severity be explicitly supplied as an argument:

BALL_LOGCB_STREAM(SEVERITY, CALLBACK) << X << Y ... ;
where X, Y, ... represents any sequence of values for which
`operator<<` is defined. The resulting formatted message string is
logged with the specified `SEVERITY`. The generated log record will
contain the `ball::UserFields` representing user fields as populated by
`CALLBACK`. Note that the callback supplied to the logging macro must
match the prototype `void (*)(ball::UserFields *)`.
#define BALL_LOGCB_STREAM(BALL_SEVERITY, CALLBACK)
Definition ball_log.h:1313

The remaining macros are based on printf-style format specifications:

BALL_LOGVA_TRACE(MSG, ...);
BALL_LOGVA_DEBUG(MSG, ...);
BALL_LOGVA_INFO( MSG, ...);
BALL_LOGVA_WARN( MSG, ...);
BALL_LOGVA_ERROR(MSG, ...);
BALL_LOGVA_FATAL(MSG, ...);
Format the specified `...` optional arguments, if any, according to the
`printf`-style format specification in the specified `MSG` (assumed to
be of type convertible to `const char *`) and log the resulting
formatted message string with the severity indicated by the name of the
macro (e.g., `BALL_LOGVA_INFO` logs with severity
`ball::Severity::e_INFO`). The behavior is undefined unless the number
and types of optional arguments are compatible with the format
specification in `MSG`. Note that each use of these macros must be
terminated by a `;`.
#define BALL_LOGVA_DEBUG(...)
Definition ball_log.h:1426
#define BALL_LOGVA_FATAL(...)
Definition ball_log.h:1438
#define BALL_LOGVA_ERROR(...)
Definition ball_log.h:1435
#define BALL_LOGVA_TRACE(...)
Definition ball_log.h:1423
#define BALL_LOGVA_INFO(...)
Definition ball_log.h:1429
#define BALL_LOGVA_WARN(...)
Definition ball_log.h:1432
@ e_INFO
Definition ball_severity.h:172

A closely-related printf-style macro, BALL_LOGVA, requires that the severity be explicitly supplied as an argument:

BALL_LOGVA(SEVERITY, MSG, ...);
Format the specified `...` optional arguments, if any, according to the
`printf`-style format specification in the specified `MSG` (assumed to
be of type convertible to `const char *`) and log the resulting
formatted message string with the specified `SEVERITY`. The behavior
is undefined unless the number and types of optional arguments are
compatible with the format specification in `MSG`. Note that each use
of this macro must be terminated by a `;`.
#define BALL_LOGVA(SEVERITY,...)
Definition ball_log.h:1405

Macros for Logging Code Blocks

The following macros allow the caller to start a code block that will be conditionally executed depending on the current logging threshold of the category that is in scope of those macros:

#define BALL_LOG_ERROR_BLOCK
Definition ball_log.h:1259
#define BALL_LOG_FATAL_BLOCK
Definition ball_log.h:1262
#define BALL_LOG_WARN_BLOCK
Definition ball_log.h:1256
#define BALL_LOG_INFO_BLOCK
Definition ball_log.h:1253
#define BALL_LOG_DEBUG_BLOCK
Definition ball_log.h:1250

A closely-related macro, BALL_LOG_STREAM_BLOCK, requires that the severity be explicitly supplied as an argument:

BALL_LOG_STREAM_BLOCK(SEVERITY) { ... }
#define BALL_LOG_STREAM_BLOCK(SEVERITY)
Definition ball_log.h:1245

Another set of macros, similar to BALL_LOG_*_BLOCK, allow the caller to specify a "callback" function that is passed the ball::UserFields * used to represent the user fields of a log record:

BALL_LOGCB_TRACE_BLOCK(CALLBACK) { ... }
BALL_LOGCB_DEBUG_BLOCK(CALLBACK) { ... }
BALL_LOGCB_INFO_BLOCK(CALLBACK) { ... }
BALL_LOGCB_WARN_BLOCK(CALLBACK) { ... }
BALL_LOGCB_ERROR_BLOCK(CALLBACK) { ... }
BALL_LOGCB_FATAL_BLOCK(CALLBACK) { ... }
#define BALL_LOGCB_INFO_BLOCK(CALLBACK)
Definition ball_log.h:1357
#define BALL_LOGCB_TRACE_BLOCK(CALLBACK)
Definition ball_log.h:1349
#define BALL_LOGCB_DEBUG_BLOCK(CALLBACK)
Definition ball_log.h:1353
#define BALL_LOGCB_ERROR_BLOCK(CALLBACK)
Definition ball_log.h:1365
#define BALL_LOGCB_WARN_BLOCK(CALLBACK)
Definition ball_log.h:1361
#define BALL_LOGCB_FATAL_BLOCK(CALLBACK)
Definition ball_log.h:1369

A closely-related macro, BALL_LOGCB_STREAM_BLOCK, requires that the severity be explicitly supplied as an argument:

BALL_LOGCB_STREAM_BLOCK(SEVERITY, CALLBACK) { ... }
#define BALL_LOGCB_STREAM_BLOCK(BALL_SEVERITY, CALLBACK)
Definition ball_log.h:1346

Within the logging code block a special macro, BALL_LOG_OUTPUT_STREAM, provides access to the log stream.

Utility Macros

The following utility macro is intended for special-purpose use for fine-tuning logging behavior. A use of this macro requires that a logging category (as established by the macros defined above) be in scope at the point where the macro is used.

Return `true` if the specified `SEVERITY` is at least as severe as any
of the threshold levels of the logging category that is in scope, and
`false` otherwise.
#define BALL_LOG_IS_ENABLED(SEVERITY)
Definition ball_log.h:1445

Usage

The following code fragments illustrate the standard pattern of macro usage.

Example 1: A Basic Logging Example

The following trivial example shows how to use the logging macros to log messages at various levels of severity.

First, we initialize the log category within the context of this function. The logging macros such as BALL_LOG_ERROR will not compile unless a category has been specified in the current lexical scope:

BALL_LOG_SET_CATEGORY("EXAMPLE.CATEGORY");
#define BALL_LOG_SET_CATEGORY(CATEGORY)
Definition ball_log.h:1041

Then, we record messages at various levels of severity. These messages will be conditionally written to the log depending on the current logging threshold of the category (configured using the ball::LoggerManager singleton):

BALL_LOG_FATAL << "Write this message to the log if the log threshold "
<< "is above 'ball::Severity::e_FATAL' (i.e., 32).";
BALL_LOG_TRACE << "Write this message to the log if the log threshold "
<< "is above 'ball::Severity::e_TRACE' (i.e., 192).";

Next, we demonstrate how to use proprietary code within logging macros. Suppose you want to add the content of a vector to the log trace:

bsl::vector<int> myVector(4, 328);
BALL_LOG_OUTPUT_STREAM << "myVector = [ ";
unsigned int position = 0;
for (bsl::vector<int>::const_iterator it = myVector.begin(),
end = myVector.end();
it != end;
++it, ++position) {
BALL_LOG_OUTPUT_STREAM << position << ':' << *it << ' ';
}
}
Definition bslstl_vector.h:1025
VALUE_TYPE const * const_iterator
Definition bslstl_vector.h:1058
#define BALL_LOG_OUTPUT_STREAM
Definition ball_log.h:1035

Note that the code block will be conditionally executed depending on the current logging threshold of the category. The code within the block must not produce any side effects, because its execution depends on the current logging configuration. The special macro BALL_LOG_OUTPUT_STREAM provides access to the log stream within the block.

Example 2: Setting the Current Log Category

This example provides more detail on setting the log category in the current lexical scope. The following macro instantiation sets the category for logging to be "EQUITY.NASD" in the enclosing lexical scope:

BALL_LOG_SET_CATEGORY("EQUITY.NASD")

Note that this macro must not be used at file scope and it can be used at most once in any given block (or else a compiler diagnostic will result). A different category may be established to override one that is in effect, but it must occur in a nested scope. In any case, a use of this macro (or of BALL_LOG_SET_DYNAMIC_CATEGORY) must be visible from within the lexical scope of every use of the log-generating macros. The following fragment of code shows how to set a different category in a nested inner block that hides a category set in an enclosing block:

void logIt()
{
BALL_LOG_SET_CATEGORY("EQUITY.NASD")
// Logging to category "EQUITY.NASD" unless overridden in a nested
// block.
// [*] ...
{
// [*] ...
// Still logging to category "EQUITY.NASD".
BALL_LOG_SET_CATEGORY("EQUITY.NASD.SUNW")
// Now logging to category "EQUITY.NASD.SUNW".
// [*] ...
}
// Again logging to category "EQUITY.NASD".
// [*] ...
}

Within logIt, a requisite logging category is visible at each of the locations marked by [*].

Example 3: C++ IO Streams-Style Logging Macros

The preferred logging method we use, the iostream-style macros such as BALL_LOG_INFO, allow streaming via the bsl::ostream class and the C++ stream operator <<. An advantage the C++ streaming style has over the printf style output (shown below in example 4) is that complex types often have the operator<<(ostream&, const TYPE&) function overloaded so that they are able to be easily streamed to output. We demonstrate this here using C++ streaming to stream a bdlt::Date to output:

int lotSize = 400;
const char *ticker = "SUNW";
double price = 5.65;
// Trading on a market that settles 3 days in the future.
BALL_LOG_SET_CATEGORY("EQUITY.NASD")
Definition bdlt_date.h:294
Date date() const
Return the value of the "date" part of this object.
Definition bdlt_datetime.h:2164
static Datetime local()
Definition bdlt_currenttime.h:280

We are logging with category "EQUITY.NASD", which is configured for a pass-through level of e_INFO, from here on. We output a line using the BALL_LOG_INFO macro:

BALL_LOG_INFO << "[1] " << lotSize
<< " shares of " << ticker
<< " sold at " << price
<< " settlement date " << settle;

The above results in the following single-line message being output:

<ts> <pid> <tid> INFO x.cpp 1161 EQUITY.NASD [1] 400 shares of SUNW sold
at 5.65 settlement date 17FEB2017

<ts> is the timestamp, <pid> is the process id, <tid> is the thread id, x.cpp is the expansion of the __FILE__ macro that is the name of the source file containing the call, 1161 is the line number of the call, and the trailing date following "settlement date" is the value of settle.

Next, we set the category to "EQUITY.NASD.SUNW", which has been defined with ball::Administration::addCategory with its pass-through level set to e_INFO and the trigger levels set at or above e_ERROR, so a level of e_WARN also passes through:

{
BALL_LOG_SET_CATEGORY("EQUITY.NASD.SUNW")
// Now logging with category "EQUITY.NASD.SUNW".
BALL_LOG_WARN << "[2] " << lotSize
<< " shares of " << ticker
<< " sold at " << price
<< " settlement date " << settle;
}

The above results in the following message to category "EQUITY.NASD.SUNW":

<ts> <pid> <tid> WARN x.cpp 1185 EQUITY.NASD.SUNW [2] 400 shares of SUNW
sold at 5.65 settlement date 17FEB2017

Now, the category "EQUITY.NASD.SUNW" just went out of scope and category "EQUITY.NASD" is visible again, so it applies to the following:

BALL_LOG_INFO << "[3] " << lotSize
<< " shares of " << ticker
<< " sold at " << price
<< " settlement date " << settle;

Finally, the above results in the following single-line message being output:

<ts> <pid> <tid> INFO x.cpp 1198 EQUITY.NASD [3] 400 shares of SUNW sold
at 5.65 settlement date 17FEB2017

The settlement date was appended to the message as a simple illustration of the added flexibility provided by the C++ stream-based macros. This last message was logged to category "EQUITY.NASD" at severity level ball::Severity::e_INFO.

The C++ stream-based macros, as opposed to the printf-style macros, ensure at compile-time that no run-time format mismatches will occur. Use of the stream-based logging style exclusively will likely lead to clearer, more maintainable code with fewer initial defects.

Note that all uses of the log-generating macros, both printf-style and C++ stream-based, must occur within function scope (i.e., not at file scope).

Example 4: printf-Style Output

In the following example, we expand the logIt function (defined above) to log two messages using the BALL_LOGVA_INFO logging macro provided by this component. This variadic macro takes a format string and a variable-length series of arguments, similar to printf.

int lotSize = 400;
const char *ticker = "SUNW";
double price = 5.65;
// Trading on a market that settles 3 days in the future.

Because we can't easily printf complex types like bdlt::Date or bsl::string, we have to convert settleDate to a const char * ourselves. Note that all this additional work was unnecessary in Example 3 when we used the C++ iostream-style, rather than the printf-style, macros.

settleOss << settleDate;
const bsl::string& settleStr = settleOss.str();
const char *settle = settleStr.c_str();
Definition bslstl_ostringstream.h:175
void str(const StringType &value)
Definition bslstl_ostringstream.h:581
Definition bslstl_string.h:1281
const CHAR_TYPE * c_str() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_string.h:6705

We set logging with category "EQUITY.NASD", which was configured for a pass-through severity level of e_INFO, and call BALL_LOGVA_INFO to print our trade:

BALL_LOG_SET_CATEGORY("EQUITY.NASD")
BALL_LOGVA_INFO("[4] %d shares of %s sold at %f settlement date %s\n",
lotSize, ticker, price, settle);

The above results in the following single-line message being output to category "EQUITY.NASD.SUNW" at severity level ball::Severity::e_INFO:

<ts> <pid> <tid> INFO x.cpp 1256 EQUITY.NASD [4] 400 shares of SUNW sold
at 5.650000 settlement date 17FEB2017

In the above, <ts> is the timestamp, <pid> is the process id, <tid> is the thread id, x.cpp is the expansion of the __FILE__ macro that is the name of the source file containing the call, and 1256 is the line number of the call.

Note that the first argument supplied to the BALL_LOGVA_INFO macro is a printf-style format specification.

Next, we set the category to "EQUITY.NASD.SUNW", which is configured for a pass-through severity level of e_INFO:

{
BALL_LOG_SET_CATEGORY("EQUITY.NASD.SUNW")
// Now logging with category "EQUITY.NASD.SUNW".
BALL_LOGVA_WARN("[5] %d shares of %s sold at %f settlement date %s\n",
lotSize, ticker, price, settle);
}

The above results in the following single-line message to category "EQUITY.NASD.SUNW":

<ts> <pid> <tid> WARN x.cpp 1281 EQUITY.NASD.SUNW [5] 400 shares of SUNW
sold at 5.650000 settlement date 17FEB2017

Now, the category "EQUITY.NASD.SUNW" just went out of scope and category "EQUITY.NASD" is visible again, so it applies to the following:

BALL_LOGVA_INFO("[6] %d shares of %s sold at %f settlement date %s\n",
lotSize, ticker, price, settle);

Finally, the above results in the following single-line message being output:

<ts> <pid> <tid> INFO x.cpp 1294 EQUITY.NASD [6] 400 shares of SUNW sold
at 5.650000 settlement date 17FEB2017

Example 5: Dynamic Categories

Logging must sometimes be controlled by parameters that are not available until run-time. The BALL_LOG_SET_DYNAMIC_CATEGORY macro sets a category each time it is invoked (unlike BALL_LOG_SET_CATEGORY, which sets a category only on the first invocation and uses the cached address of the category on subsequent invocations). The category name in the following processSecurity function is a combination of a static prefix and the (dynamic) exchange argument:

void processSecurity(const char *security, const char *exchange)
{
bsl::string categoryName("EXCHANGE:");
categoryName.append(exchange);
BALL_LOG_SET_DYNAMIC_CATEGORY(categoryName.c_str());
BALL_LOG_TRACE << "processing: " << security;
// ...
}
#define BALL_LOG_SET_DYNAMIC_CATEGORY(CATEGORY)
Definition ball_log.h:1064

Now logging can be controlled independently for each exchange.

WARNING: Along with the added flexibility provided by dynamic categories comes the additional overhead of computing and setting a category on each invocation. Consequently, dynamic categories should be used SPARINGLY in most applications.

Example 6: Rule-Based Logging

The following example demonstrates the use of attributes and rules to conditionally enable logging.

We start by defining a function, processData, that is passed data in a vector<char> and information about the user who sent the data. This example function performs no actual processing, but does log a single message at the ball::Severity::e_DEBUG threshold level. The processData function also adds the user information passed to this function to the thread's attribute context. We will use these attributes later, to create a logging rule that enables verbose logging only for a particular user.

/// Process the specified `data` associated with the specified Bloomberg
/// `uuid`, `luw`, and `terminalNumber`.
void processData(int uuid,
int luw,
int terminalNumber,
const bsl::vector<char>& data)
{
(void)data; // suppress "unused" warning

We add our attributes using ball::ScopedAttribute, which adds an attribute container with one attribute to a list of containers. This is easy and efficient if the number of attributes is small, but should not be used if there are a large number of attributes. If motivated, we could use ball::DefaultAttributeContainer, which provides an efficient container for a large number of attributes, or even create a more efficient attribute container implementation specifically for these three attributes (uuid, luw, and terminalNumber). See ball_scopedattributes (plural) for an example of using a different attribute container, and ball_attributecontainer for an example of creating a custom attribute container.

// We use `ball::ScopedAttribute` here because the number of
// attributes is relatively small.
ball::ScopedAttribute uuidAttribute("mylibrary.uuid", uuid);
ball::ScopedAttribute luwAttribute("mylibrary.luw", luw);
ball::ScopedAttribute termNumAttribute("mylibrary.terminalNumber",
terminalNumber);
Definition ball_scopedattribute.h:230

In this simplified example we perform no actual processing, and simply log a message at the ball::Severity::e_DEBUG level.

BALL_LOG_SET_CATEGORY("EXAMPLE.CATEGORY");
BALL_LOG_DEBUG << "An example message";

Notice that if we were not using a "scoped" attribute container like that provided automatically by ball::ScopedAttribute (e.g., if we were using a local ball::DefaultAttributeContainer instead), then the container must be removed from the ball::AttributeContext before it is destroyed! See ball_scopedattributes (plural) for an example.

}

Next we demonstrate how to create a logging rule that sets the pass-through logging threshold to ball::Severity::e_TRACE (i.e., enables verbose logging) for a particular user when calling the processData function defined above.

We start by creating the singleton logger manager that we configure with the stream observer and a default configuration. We then call the processData function: This first call to processData will not result in any logged messages because processData logs its message at the ball::Severity::e_DEBUG level, which is below the default configured logging threshold.

bsl::make_shared<ball::StreamObserver>(&bsl::cout);
BALL_LOG_SET_CATEGORY("EXAMPLE.CATEGORY");
BALL_LOG_ERROR << "Processing the first message.";
processData(3938908, 2, 9001, message);
Definition ball_loggermanagerconfiguration.h:281
Definition ball_loggermanager.h:2073
static LoggerManager & singleton()
Definition ball_loggermanager.h:2290
int registerObserver(const bsl::shared_ptr< Observer > &observer, const bsl::string_view &observerName)
Definition ball_loggermanager.h:2348
Definition bslstl_sharedptr.h:1830

Now we add a logging rule, setting the pass-through threshold to be ball::Severity::e_TRACE (i.e., enabling verbose logging) if the thread's context contains an attribute with name "mylibrary.uuid" with value 3938908. Note that we use the wild-card value * for the category so that the ball::Rule rule will apply to all categories.

ball::Rule rule("*", 0, ball::Severity::e_TRACE, 0, 0);
rule.addAttribute(ball::ManagedAttribute("mylibrary.uuid", 3938908));
BALL_LOG_ERROR << "Processing the second message.";
processData(3938908, 2, 9001, message);
int addRule(const Rule &value)
Definition ball_loggermanager.h:2373
Definition ball_managedattribute.h:117
Definition ball_rule.h:177

The final call to the processData function below, passes a uuid of 2171395 (not 3938908) so the logging rule we defined will not apply and no message will be logged.

BALL_LOG_ERROR << "Processing the third message.";
processData(2171395, 2, 9001, message);

The resulting logged output for this example looks like the following:

ERROR example.cpp:105 EXAMPLE.CATEGORY Processing the first message.
ERROR example.cpp:117 EXAMPLE.CATEGORY Processing the second message.
DEBUG example.cpp:35 EXAMPLE.CATEGORY An example message
ERROR example.cpp:129 EXAMPLE.CATEGORY Processing the third message.

Example 7: Logging Using a Callback

The following example demonstrates how to register a logging callback. The C++ stream-based macros that take a callback are particularly useful to seamlessly populate the user fields of a record, thus simplifying the logging line.

We define a callback function populateUsingPoint that appends to the specified fields the attributes of the point to log:

/// Append to the specified `list` the name, x value, and y value of
/// the specified `point`.
void populateUsingPoint(ball::UserFields *fields, const Point& point)
{
fields->appendString(point.name());
fields->appendInt64(point.x());
fields->appendInt64(point.y());
}
int validatePoint(const Point& point)
{
BALL_LOG_SET_CATEGORY("EXAMPLE.CATEGORY");
void appendInt64(bsls::Types::Int64 value)
Definition ball_userfields.h:337
void appendString(const bsl::string_view &value)
Definition ball_userfields.h:349

We now bind our callback function populateUsingPoint and the supplied point to a functor object we will pass to the logging callback. Note that the callback supplied to the logging macro must match the prototype void (*)(ball::UserFields *).

bsl::function <void(ball::UserFields *)> callback;
callback = bdlf::BindUtil::bind(&populateUsingPoint,
point);
int numErrors = 0;
if (point.x() > 255) {
BALL_LOGCB_ERROR(callback) << "X > 255";
++numErrors;
}
if (point.x() < -255) {
BALL_LOGCB_ERROR(callback) << "X < -255";
++numErrors;
}
if (point.y() > 255) {
BALL_LOGCB_ERROR(callback) << "Y > 255";
++numErrors;
}
if (point.y() < -255) {
BALL_LOGCB_ERROR(callback) << "Y < -255";
++numErrors;
}
return numErrors;
}
static Bind< bslmf::Nil, t_FUNC, Bind_BoundTuple0 > bind(t_FUNC func)
Definition bdlf_bind.h:1830
Forward declaration.
Definition bslstl_function.h:934
const PlaceHolder< 1 > _1

Example 8: Class-Scope Logging

The following example demonstrates how to define and use logging categories that have class scope.

First, we define a class, Thing, for which we want to do class-scope logging. The use of the BALL_LOG_SET_CLASS_CATEGORY macro generates the requisite declarations within the definition of the class. We have used the macro in a private section of the interface, which should be preferred, but public (or protected) is fine, too:

// pckg_thing.h
namespace pckg {
class Thing {
// ...
private:
public:
// ...
// MANIPULATORS
/// Log to the class-scope category "PCKG.THING" if the specified
/// `useClassCategory` flag is `true`, and to the block-scope
/// category "X.Y.Z" otherwise.
void outOfLineMethodThatLogs(bool useClassCategory);
// ...
// ACCESSORS
/// Log a record to the class-scope category "PCKG.THING".
void inlineMethodThatLogs() const;
};
#define BALL_LOG_SET_CLASS_CATEGORY(CATEGORY)
Definition ball_log.h:1088

Next, we define the inlineMethodThatLogs method inline within the header file and log to the class-scope category using BALL_LOG_TRACE. Since there is no other category in scope, the record is necessarily logged to the "PCKG.THING" category that is within the scope of the Thing class:

// ...
// ACCESSORS
inline
void Thing::inlineMethodThatLogs() const
{
BALL_LOG_TRACE << "log to PCKG.THING";
}
} // close namespace pckg

Now, we define the outOfLineMethodThatLogs method within the .cpp file. On each invocation, this method logs one record using BALL_LOG_TRACE. It logs to the "PCKG.THING" class-scope category if useClassCategory is true, and logs to the "X.Y.Z" block-scope category otherwise:

// pckg_thing.cpp
namespace pckg {
// ...
// MANIPULATORS
void Thing::outOfLineMethodThatLogs(bool useClassCategory)
{
if (useClassCategory) {
BALL_LOG_TRACE << "log to PCKG.THING";
}
else {
BALL_LOG_TRACE << "log to X.Y.Z";
}
}
} // close namespace pckg

Finally, note that both block-scope and class-scope categories can be logged to within the same block. For example, the following block within a Thing method would first log to "PCKG.THING" then log to "X.Y.Z":

{
BALL_LOG_TRACE << "log to PCKG.THING";
BALL_LOG_TRACE << "log to X.Y.Z";
}

Macro Definition Documentation

◆ BALL_LOG_CATEGORY

#define BALL_LOG_CATEGORY    (ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER)->category())

◆ BALL_LOG_DEBUG

#define BALL_LOG_DEBUG
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_DEBUG) \
#define BALL_LOG_STREAM_CONST_IMP(SEVERITY)
Definition ball_log.h:1181

◆ BALL_LOG_DEBUG_BLOCK

#define BALL_LOG_DEBUG_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_DEBUG)

◆ BALL_LOG_END

#define BALL_LOG_END   ""

◆ BALL_LOG_ERROR

#define BALL_LOG_ERROR
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_ERROR) \

◆ BALL_LOG_ERROR_BLOCK

#define BALL_LOG_ERROR_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_ERROR)

◆ BALL_LOG_FATAL

#define BALL_LOG_FATAL
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_FATAL) \

◆ BALL_LOG_FATAL_BLOCK

#define BALL_LOG_FATAL_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_FATAL)

◆ BALL_LOG_INFO

#define BALL_LOG_INFO
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_INFO) \

◆ BALL_LOG_INFO_BLOCK

#define BALL_LOG_INFO_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_INFO)

◆ BALL_LOG_IS_ENABLED

#define BALL_LOG_IS_ENABLED (   SEVERITY)
Value:
((BALL_LOG_THRESHOLD >= (SEVERITY)) \
&& BloombergLP::ball::Log::isCategoryEnabled( \
ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER), \
(SEVERITY)))
#define BALL_LOG_THRESHOLD
Definition ball_log.h:1030

◆ BALL_LOG_OUTPUT_STREAM

#define BALL_LOG_OUTPUT_STREAM   (ball_log_lOg_StReAm.stream())

◆ BALL_LOG_RECORD

#define BALL_LOG_RECORD   (ball_log_lOg_StReAm.record())

◆ BALL_LOG_SET_CATEGORY

#define BALL_LOG_SET_CATEGORY (   CATEGORY)
Value:
static BloombergLP::ball::CategoryHolder BALL_LOG_CATEGORYHOLDER = { \
{ BloombergLP::ball::CategoryHolder::e_UNINITIALIZED_CATEGORY }, \
{ 0 }, { 0 } \
}; \
BloombergLP::ball::Log::setCategory(&BALL_LOG_CATEGORYHOLDER, \
CATEGORY); \
}
#define BALL_LOG_CATEGORY
Definition ball_log.h:1027
#define BSLS_PERFORMANCEHINT_UNLIKELY_HINT
Definition bsls_performancehint.h:484
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452

◆ BALL_LOG_SET_CATEGORY_HIERARCHICALLY

#define BALL_LOG_SET_CATEGORY_HIERARCHICALLY (   CATEGORY)
Value:
static BloombergLP::ball::CategoryHolder BALL_LOG_CATEGORYHOLDER = { \
{ BloombergLP::ball::CategoryHolder::e_UNINITIALIZED_CATEGORY }, \
{ 0 }, { 0 } \
}; \
BloombergLP::ball::Log::setCategoryHierarchically( \
&BALL_LOG_CATEGORYHOLDER, \
CATEGORY); \
}

◆ BALL_LOG_SET_CLASS_CATEGORY

#define BALL_LOG_SET_CLASS_CATEGORY (   CATEGORY)
Value:
static \
const BloombergLP::ball::CategoryHolder *ball_log_getCategoryHolder( \
const BloombergLP::ball::CategoryHolder& categoryHolder) \
{ \
return &categoryHolder; \
} \
static \
const BloombergLP::ball::CategoryHolder *ball_log_getCategoryHolder(int) \
{ \
static BloombergLP::ball::CategoryHolder holder = { \
{ BloombergLP::ball::CategoryHolder::e_UNINITIALIZED_CATEGORY }, \
{ 0 }, { 0 } \
}; \
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!holder.category())) { \
BloombergLP::ball::Log::setCategory(&holder, CATEGORY); \
} \
return &holder; \
} \
enum { BALL_LOG_CATEGORYHOLDER = 0 }

◆ BALL_LOG_SET_CLASS_CATEGORY_HIERARCHICALLY

#define BALL_LOG_SET_CLASS_CATEGORY_HIERARCHICALLY (   CATEGORY)
Value:
static \
const BloombergLP::ball::CategoryHolder *ball_log_getCategoryHolder( \
const BloombergLP::ball::CategoryHolder& categoryHolder) \
{ \
return &categoryHolder; \
} \
static \
const BloombergLP::ball::CategoryHolder *ball_log_getCategoryHolder(int) \
{ \
static BloombergLP::ball::CategoryHolder holder = { \
{ BloombergLP::ball::CategoryHolder::e_UNINITIALIZED_CATEGORY }, \
{ 0 }, { 0 } \
}; \
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!holder.category())) { \
BloombergLP::ball::Log::setCategoryHierarchically(&holder, \
CATEGORY); \
} \
return &holder; \
} \
enum { BALL_LOG_CATEGORYHOLDER = 0 }

◆ BALL_LOG_SET_DYNAMIC_CATEGORY

#define BALL_LOG_SET_DYNAMIC_CATEGORY (   CATEGORY)
Value:
const BloombergLP::ball::Category *BALL_LOG_DYNAMIC_CATEGORY = \
BloombergLP::ball::Log::setCategory(CATEGORY); \
BloombergLP::ball::CategoryHolder BALL_LOG_CATEGORYHOLDER = { \
{ BloombergLP::ball::CategoryHolder::e_DYNAMIC_CATEGORY }, \
{ const_cast<BloombergLP::ball::Category *>( \
BALL_LOG_DYNAMIC_CATEGORY) }, \
{ 0 } \
};

◆ BALL_LOG_SET_DYNAMIC_CATEGORY_HIERARCHICALLY

#define BALL_LOG_SET_DYNAMIC_CATEGORY_HIERARCHICALLY (   CATEGORY)
Value:
const BloombergLP::ball::Category *BALL_LOG_DYNAMIC_CATEGORY = \
BloombergLP::ball::Log::setCategoryHierarchically(CATEGORY); \
BloombergLP::ball::CategoryHolder BALL_LOG_CATEGORYHOLDER = { \
{ BloombergLP::ball::CategoryHolder::e_DYNAMIC_CATEGORY }, \
{ const_cast<BloombergLP::ball::Category *>( \
BALL_LOG_DYNAMIC_CATEGORY) }, \
{ 0 } \
};

◆ BALL_LOG_SET_NAMESPACE_CATEGORY

#define BALL_LOG_SET_NAMESPACE_CATEGORY (   CATEGORY)
Value:
namespace { \
static \
const BloombergLP::ball::CategoryHolder *ball_log_getCategoryHolder(int) \
{ \
static BloombergLP::ball::CategoryHolder holder = { \
{ BloombergLP::ball::CategoryHolder::e_UNINITIALIZED_CATEGORY }, \
{ 0 }, { 0 } \
}; \
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!holder.category())) { \
BloombergLP::ball::Log::setCategory(&holder, CATEGORY); \
} \
return &holder; \
} \
enum { BALL_LOG_CATEGORYHOLDER = 0 }; \
}

◆ BALL_LOG_SET_NAMESPACE_CATEGORY_HIERARCHICALLY

#define BALL_LOG_SET_NAMESPACE_CATEGORY_HIERARCHICALLY (   CATEGORY)
Value:
namespace { \
static \
const BloombergLP::ball::CategoryHolder *ball_log_getCategoryHolder(int) \
{ \
static BloombergLP::ball::CategoryHolder holder = { \
{ BloombergLP::ball::CategoryHolder::e_UNINITIALIZED_CATEGORY }, \
{ 0 }, { 0 } \
}; \
if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(!holder.category())) { \
BloombergLP::ball::Log::setCategoryHierarchically(&holder, \
CATEGORY); \
} \
return &holder; \
} \
enum { BALL_LOG_CATEGORYHOLDER = 0 }; \
}

◆ BALL_LOG_STREAM

#define BALL_LOG_STREAM (   SEVERITY)     BALL_LOG_STREAM_IMP((SEVERITY)) BALL_LOG_OUTPUT_STREAM

◆ BALL_LOG_STREAM_BLOCK

#define BALL_LOG_STREAM_BLOCK (   SEVERITY)    BALL_LOG_STREAM_IMP((SEVERITY))

◆ BALL_LOG_STREAM_CONST_IMP

#define BALL_LOG_STREAM_CONST_IMP (   SEVERITY)
Value:
for (const BloombergLP::ball::CategoryHolder *ball_log_cAtEgOrYhOlDeR = \
BloombergLP::ball::Log::categoryHolderIfEnabled<(SEVERITY)>( \
ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER)); \
ball_log_cAtEgOrYhOlDeR; \
) \
for (BloombergLP::ball::Log_Stream ball_log_lOg_StReAm( \
ball_log_cAtEgOrYhOlDeR->category(), \
__FILE__, \
__LINE__, \
(SEVERITY)); \
ball_log_cAtEgOrYhOlDeR; \
ball_log_cAtEgOrYhOlDeR = 0)

◆ BALL_LOG_STREAM_IMP

#define BALL_LOG_STREAM_IMP (   SEVERITY)
Value:
for (const BloombergLP::ball::CategoryHolder *ball_log_cAtEgOrYhOlDeR = \
ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER); \
ball_log_cAtEgOrYhOlDeR \
&& ball_log_cAtEgOrYhOlDeR->threshold() >= (SEVERITY) \
&& BloombergLP::ball::Log::isCategoryEnabled(ball_log_cAtEgOrYhOlDeR, \
(SEVERITY)); \
) \
for (BloombergLP::ball::Log_Stream ball_log_lOg_StReAm( \
ball_log_cAtEgOrYhOlDeR->category(), \
__FILE__, \
__LINE__, \
(SEVERITY)); \
ball_log_cAtEgOrYhOlDeR; \
ball_log_cAtEgOrYhOlDeR = 0)

◆ BALL_LOG_THRESHOLD

#define BALL_LOG_THRESHOLD    (ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER)->threshold())

◆ BALL_LOG_TRACE

#define BALL_LOG_TRACE
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_TRACE) \

◆ BALL_LOG_TRACE_BLOCK

#define BALL_LOG_TRACE_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_TRACE)

◆ BALL_LOG_WARN

#define BALL_LOG_WARN
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_WARN) \

◆ BALL_LOG_WARN_BLOCK

#define BALL_LOG_WARN_BLOCK    BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_WARN)

◆ BALL_LOGCB_DEBUG

#define BALL_LOGCB_DEBUG (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_DEBUG, \
(CALLBACK)) \
#define BALL_LOGCB_STREAM_CONST_IMP(SEVERITY, CALLBACK)
Definition ball_log.h:1274

◆ BALL_LOGCB_DEBUG_BLOCK

#define BALL_LOGCB_DEBUG_BLOCK (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_DEBUG, \
(CALLBACK))

◆ BALL_LOGCB_END

#define BALL_LOGCB_END   ""

◆ BALL_LOGCB_ERROR

#define BALL_LOGCB_ERROR (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_ERROR, \
(CALLBACK)) \

◆ BALL_LOGCB_ERROR_BLOCK

#define BALL_LOGCB_ERROR_BLOCK (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_ERROR, \
(CALLBACK))

◆ BALL_LOGCB_FATAL

#define BALL_LOGCB_FATAL (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_FATAL, \
(CALLBACK)) \

◆ BALL_LOGCB_FATAL_BLOCK

#define BALL_LOGCB_FATAL_BLOCK (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_FATAL, \
(CALLBACK))

◆ BALL_LOGCB_INFO

#define BALL_LOGCB_INFO (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_INFO, \
(CALLBACK)) \

◆ BALL_LOGCB_INFO_BLOCK

#define BALL_LOGCB_INFO_BLOCK (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_INFO, \
(CALLBACK))

◆ BALL_LOGCB_STREAM

#define BALL_LOGCB_STREAM (   BALL_SEVERITY,
  CALLBACK 
)     BALL_LOGCB_STREAM_IMP((BALL_SEVERITY), (CALLBACK)) BALL_LOG_OUTPUT_STREAM

◆ BALL_LOGCB_STREAM_BLOCK

#define BALL_LOGCB_STREAM_BLOCK (   BALL_SEVERITY,
  CALLBACK 
)     BALL_LOGCB_STREAM_IMP((BALL_SEVERITY), (CALLBACK))

◆ BALL_LOGCB_STREAM_CONST_IMP

#define BALL_LOGCB_STREAM_CONST_IMP (   SEVERITY,
  CALLBACK 
)
Value:
for (const BloombergLP::ball::CategoryHolder *ball_log_cAtEgOrYhOlDeR = \
BloombergLP::ball::Log::categoryHolderIfEnabled<(SEVERITY)>( \
ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER)); \
ball_log_cAtEgOrYhOlDeR; \
) \
for (BloombergLP::ball::Log_Stream ball_log_lOg_StReAm( \
ball_log_cAtEgOrYhOlDeR->category(), \
__FILE__, \
__LINE__, \
(SEVERITY)); \
ball_log_cAtEgOrYhOlDeR \
&& (CALLBACK(&BALL_LOG_RECORD->customFields()), true); \
ball_log_cAtEgOrYhOlDeR = 0)
#define BALL_LOG_RECORD
Definition ball_log.h:1033

◆ BALL_LOGCB_STREAM_IMP

#define BALL_LOGCB_STREAM_IMP (   SEVERITY,
  CALLBACK 
)
Value:
for (const BloombergLP::ball::CategoryHolder *ball_log_cAtEgOrYhOlDeR = \
ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER); \
ball_log_cAtEgOrYhOlDeR \
&& ball_log_cAtEgOrYhOlDeR->threshold() >= (SEVERITY) \
&& BloombergLP::ball::Log::isCategoryEnabled(ball_log_cAtEgOrYhOlDeR, \
(SEVERITY)); \
) \
for (BloombergLP::ball::Log_Stream ball_log_lOg_StReAm( \
ball_log_cAtEgOrYhOlDeR->category(), \
__FILE__, \
__LINE__, \
(SEVERITY)); \
ball_log_cAtEgOrYhOlDeR \
&& (CALLBACK(&BALL_LOG_RECORD->customFields()), true); \
ball_log_cAtEgOrYhOlDeR = 0)

◆ BALL_LOGCB_TRACE

#define BALL_LOGCB_TRACE (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_TRACE, \
(CALLBACK)) \

◆ BALL_LOGCB_TRACE_BLOCK

#define BALL_LOGCB_TRACE_BLOCK (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_TRACE, \
(CALLBACK))

◆ BALL_LOGCB_WARN

#define BALL_LOGCB_WARN (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_WARN, \
(CALLBACK)) \

◆ BALL_LOGCB_WARN_BLOCK

#define BALL_LOGCB_WARN_BLOCK (   CALLBACK)
Value:
BALL_LOGCB_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_WARN, \
(CALLBACK))

◆ BALL_LOGVA

#define BALL_LOGVA (   SEVERITY,
  ... 
)
Value:
do { \
const BloombergLP::ball::CategoryHolder *ball_log_cAtEgOrYhOlDeR = \
ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER); \
if (ball_log_cAtEgOrYhOlDeR->threshold() >= (SEVERITY) && \
BloombergLP::ball::Log::isCategoryEnabled(ball_log_cAtEgOrYhOlDeR, \
(SEVERITY))) { \
BloombergLP::ball::Log_Formatter ball_log_fOrMaTtEr( \
ball_log_cAtEgOrYhOlDeR->category(), \
__FILE__, \
__LINE__, \
(SEVERITY)); \
BloombergLP::ball::Log::format(ball_log_fOrMaTtEr.messageBuffer(), \
ball_log_fOrMaTtEr.messageBufferLen(), \
__VA_ARGS__); \
} \
} while(0)

◆ BALL_LOGVA_CONST_IMP

#define BALL_LOGVA_CONST_IMP (   SEVERITY,
  ... 
)
Value:
do { \
if (const BloombergLP::ball::CategoryHolder *ball_log_cAtEgOrYhOlDeR = \
BloombergLP::ball::Log::categoryHolderIfEnabled<(SEVERITY)>( \
ball_log_getCategoryHolder(BALL_LOG_CATEGORYHOLDER))) { \
BloombergLP::ball::Log_Formatter ball_log_fOrMaTtEr( \
ball_log_cAtEgOrYhOlDeR->category(), \
__FILE__, \
__LINE__, \
(SEVERITY)); \
BloombergLP::ball::Log::format(ball_log_fOrMaTtEr.messageBuffer(), \
ball_log_fOrMaTtEr.messageBufferLen(), \
__VA_ARGS__); \
} \
} while(0)

◆ BALL_LOGVA_DEBUG

#define BALL_LOGVA_DEBUG (   ...)     BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_DEBUG, __VA_ARGS__)

◆ BALL_LOGVA_ERROR

#define BALL_LOGVA_ERROR (   ...)     BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_ERROR, __VA_ARGS__)

◆ BALL_LOGVA_FATAL

#define BALL_LOGVA_FATAL (   ...)     BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_FATAL, __VA_ARGS__)

◆ BALL_LOGVA_INFO

#define BALL_LOGVA_INFO (   ...)     BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_INFO, __VA_ARGS__)

◆ BALL_LOGVA_TRACE

#define BALL_LOGVA_TRACE (   ...)     BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_TRACE, __VA_ARGS__)

◆ BALL_LOGVA_WARN

#define BALL_LOGVA_WARN (   ...)     BALL_LOGVA_CONST_IMP(BloombergLP::ball::Severity::e_WARN, __VA_ARGS__)