BDE 4.39.x Production Release
Loading...
Searching...
No Matches

Detailed Description

Provide macros to facilitate bsl::format logging.

Outline

Purpose

Provide macros to facilitate bsl::format logging.

Macros

See also
ball_log, bslfmt_format, bslfmt_streamed

Description

This component provides preprocessor macros that facilitate logging using standard format format strings. This component provides additional macros that build on those defined in ball_log, and this documentation assumes readers will be familiar with the terminology established by that component, such as log category, log record, log level, etc.

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.

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 of the logging macros require a logging category be established in scope – e.g., using BALL_LOG_SET_CATEGORY. For more information of setting the log category for a particular scope, see ball_log. 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_FMT_INFO("Count: {}", ++i); // (!) May or may not be incremented
#define BALL_FMT_INFO(...)
Definition ball_fmt.h:262

The following BALL_FMT_* macros, are the simplest mechanisms to format (using a standard format specification) a single message to a log:

BALL_FMT_TRACE(format_string_literal, ARG1, ARG2, ...);
BALL_FMT_DEBUG(format_string_literal, ARG1, ARG2, ...);
BALL_FMT_INFO( format_string_literal, ARG1, ARG2, ...);
BALL_FMT_WARN( format_string_literal, ARG1, ARG2, ...);
BALL_FMT_ERROR(format_string_literal, ARG1, ARG2, ...);
BALL_FMT_FATAL(format_string_literal, ARG1, ARG2, ...);
#define BALL_FMT_DEBUG(...)
Definition ball_fmt.h:258
#define BALL_FMT_TRACE(...)
Definition ball_fmt.h:254
#define BALL_FMT_FATAL(...)
Definition ball_fmt.h:274
#define BALL_FMT_ERROR(...)
Definition ball_fmt.h:270
#define BALL_FMT_WARN(...)
Definition ball_fmt.h:266

where ARG1, ARG2, ... represents any sequence of values for which a bsl::format formatter is defined. The resulting formatted message string is logged with the severity indicated by the name of the macro (e.g., BALL_FMT_TRACE logs with severity ball::Severity::e_TRACE).

Macros for Formatted Logging Inside Code Blocks

ball_log provides several kinds of macros to create potentially executed code blocks from which more complicated logging can be performed. As a reminder the most commonly used such block macros are:

#define BALL_LOG_ERROR_BLOCK
Definition ball_log.h:1492
#define BALL_LOG_FATAL_BLOCK
Definition ball_log.h:1495
#define BALL_LOG_WARN_BLOCK
Definition ball_log.h:1489
#define BALL_LOG_INFO_BLOCK
Definition ball_log.h:1486
#define BALL_LOG_DEBUG_BLOCK
Definition ball_log.h:1483
#define BALL_LOG_TRACE_BLOCK
Definition ball_log.h:1480

Please see ball_log for the other such block macros.

Within logging code blocks the special macro, BALL_FMT provides standard format-style logging into the log record being built there.

BALL_FMT(format-string-literal, X, Y, ...)
#define BALL_FMT(...)
Definition ball_fmt.h:248

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_FMT_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:1210

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_FMT_FATAL("Write this message to the log if the log threshold "
"is above 'ball::Severity::e_FATAL' (i.e., {}).", 32);
BALL_FMT_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_FMT("myVector = [ ");
unsigned int position = 0;
for (bsl::vector<int>::const_iterator it = myVector.begin(),
end = myVector.end();
it != end;
++it, ++position) {
BALL_FMT("{}:{} ", position, *it);
}
BALL_FMT("]");
}
Definition bslstl_vector.h:1120
VALUE_TYPE const * const_iterator
Definition bslstl_vector.h:1153

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_FMT provides the means to write to the log record from within the block.

Example 2: Logging Types with ostream insert operator<<

The following example shows how to use the bslfmt::streamed facility with types that have no support for bsl::formating, but have support for writing to an ostream to facilitate formatted logging.

Suppose we have a type that (we do not own, and) is some sort of identifier that is capable of "printing" itself to an ostream:

namespace abc {
class Identifier {
private:
// DATA
unsigned d_value;
public:
// CREATORS
Identifier(unsigned value) : d_value(value) {}
// ACCESSORS
unsigned value() const { return d_value; }
};
bsl::ostream& operator<<(bsl::ostream& os, const Identifier& obj)
{
return os << obj.value();
}
} // close namespace abc
bsl::ostream & operator<<(bsl::ostream &stream, const bdlat_AttributeInfo &attributeInfo)

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

BALL_LOG_SET_CATEGORY("EXAMPLE.CATEGORY");

Then, we record a message containing identifiers using bslfmt::streamed:

const abc::Identifier id(12345);
BALL_FMT_FATAL("Item {:>010} does not exist.", bslfmt::streamed(id));
// Logs: `Item 0000012345 does not exist.`
Streamed< t_STREAMABLE > streamed(const t_STREAMABLE &object)

Note that the wrapper created by bslfmt::streamed uses the ostream insert operator<< of abc::Identifier to get the characters to print and uses the syntax of string formatting for the format specification.

Macro Definition Documentation

◆ BALL_FMT

#define BALL_FMT (   ...)
Value:
bsl::format_to( \
bsl::ostreambuf_iterator<char>( \
&BALL_LOG_RECORD->fixedFields().messageStreamBuf()), \
__VA_ARGS__)
#define BALL_LOG_RECORD
Definition ball_log.h:1202

◆ BALL_FMT_DEBUG

#define BALL_FMT_DEBUG (   ...)
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_DEBUG) \
BALL_FMT(__VA_ARGS__)
#define BALL_LOG_STREAM_CONST_IMP(SEVERITY)
Definition ball_log.h:1414

◆ BALL_FMT_ERROR

#define BALL_FMT_ERROR (   ...)
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_ERROR) \
BALL_FMT(__VA_ARGS__)

◆ BALL_FMT_FATAL

#define BALL_FMT_FATAL (   ...)
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_FATAL) \
BALL_FMT(__VA_ARGS__)

◆ BALL_FMT_INFO

#define BALL_FMT_INFO (   ...)
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_INFO) \
BALL_FMT(__VA_ARGS__)

◆ BALL_FMT_TRACE

#define BALL_FMT_TRACE (   ...)
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_TRACE) \
BALL_FMT(__VA_ARGS__)

◆ BALL_FMT_WARN

#define BALL_FMT_WARN (   ...)
Value:
BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_WARN) \
BALL_FMT(__VA_ARGS__)