July 7, 2025

Introducing BALL_FMT: BALL Logger Support for std::format-style Text Formatting

BDE 4.26.0 introduced the ball_fmt component that provides logging macros that accept a format specifications and substitution parameters mirroring those introduced in standard C++20 facility bsl::format (see the article Introducing bsl::format):

 BALL_LOG_SET_CATEGORY("EXAMPLE.CATEGORY");

 BALL_FMT_TRACE("Examining record number {}...", recNumber);

 BALL_FMT_ERROR("Endpoint '{}' is not in the allowed list", endPoint);

Logging is a place where the benefits of the new standard formatting facilities really shine, allowing developers to more easily craft log messages that output in a desired format, while being more readable in source code.

Of course, it is also possible to log within a block into the same record as we can with the streaming log macros:

 bsl::vector<int> myVector(4, 328);
 BALL_LOG_TRACE_BLOCK {
     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("]");
 }

Many existing types do not (and may never) provide bsl::formatter specializations, and rely on the ostream insert operator<< to generate a text description. To overcome this gap, clients can use the new bslfmt::streamed wrapper (also released in BDE 4.26):

 BALL_LOG_SET_CATEGORY("EXAMPLE.CATEGORY");

 BALL_FMT_FATAL("Item {:>010} does not exist.", bslfmt::streamed(id));

For more details read the bslfmt::streamed Introduction and bslfmt::streamed.