BDE 4.39.x Production Release
Loading...
Searching...
No Matches
ball_fmt.h
Go to the documentation of this file.
1/// @file ball_fmt.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_fmt.h -*-C++-*-
8#ifndef INCLUDED_BALL_FMT
9#define INCLUDED_BALL_FMT
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_fmt ball_fmt
15/// @brief Provide macros to facilitate `bsl::format` logging.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_fmt
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_fmt-purpose"> Purpose</a>
25/// * <a href="#ball_fmt-macros"> Macros </a>
26/// * <a href="#ball_fmt-description"> Description </a>
27/// * <a href="#ball_fmt-thread-safety"> Thread Safety </a>
28/// * <a href="#ball_fmt-macro-reference"> Macro Reference </a>
29/// * <a href="#ball_fmt-macros-for-logging-records"> Macros for Logging Records </a>
30/// * <a href="#ball_fmt-macros-for-formatted-logging-inside-code-blocks"> Macros for Formatted Logging Inside Code Blocks </a>
31/// * <a href="#ball_fmt-usage"> Usage </a>
32/// * <a href="#ball_fmt-example-1-a-basic-logging-example"> Example 1: A Basic Logging Example </a>
33/// * <a href="#ball_fmt-example-2-logging-types-with-ostream-insert-operator"> Example 2: Logging Types with ostream insert operator<< </a>
34///
35/// # Purpose {#ball_fmt-purpose}
36/// Provide macros to facilitate `bsl::format` logging.
37///
38/// # Macros {#ball_fmt-macros}
39///
40/// - BALL_FMT: format a log record within a `*_BLOCK`
41/// - BALL_FMT_TRACE: format a log record with the `e_TRACE` level
42/// - BALL_FMT_DEBUG: format a log record with the `e_DEBUG` level
43/// - BALL_FMT_INFO: format a log record with the `e_INFO` level
44/// - BALL_FMT_WARN: format a log record with the `e_WARN` level
45/// - BALL_FMT_ERROR: format a log record with the `e_ERROR` level
46/// - BALL_FMT_FATAL: format a log record with the `e_FATAL` level
47///
48/// @see ball_log, bslfmt_format, bslfmt_streamed
49///
50/// # Description {#ball_fmt-description}
51/// This component provides preprocessor macros that facilitate
52/// logging using standard `format` format strings. This component provides
53/// additional macros that build on those defined in `ball_log`, and this
54/// documentation assumes readers will be familiar with the terminology
55/// established by that component, such as log category, log record, log level,
56/// etc.
57///
58/// ## Thread Safety {#ball_fmt-thread-safety}
59///
60///
61/// All macros defined in this component are thread-safe, and can be invoked
62/// concurrently by multiple threads.
63///
64/// Additionally, each use of a logging macro will create a distinct log record,
65/// and `ball::Observer` implementations (like those in `ball`) generally
66/// guarantee that output for different log records are not interleaved.
67///
68/// ## Macro Reference {#ball_fmt-macro-reference}
69///
70///
71/// This section documents the preprocessor macros defined in this component.
72///
73/// ### Macros for Logging Records {#ball_fmt-macros-for-logging-records}
74///
75///
76/// The macros defined in this subsection are the ones that are actually used to
77/// produce log records. A use of any of the logging macros require a logging
78/// category be established in scope -- e.g., using `BALL_LOG_SET_CATEGORY`.
79/// For more information of setting the log category for a particular scope,
80/// see `ball_log`. Note that the formatted string that is generated for the
81/// message attribute of each log record includes the category that is in scope
82/// and the filename as established by the standard `__FILE__` macro.
83///
84/// The code within any logging statement/code block must not produce any side
85/// effects because it may or may not be executed based on run-time
86/// configuration of the `ball` logging subsystem:
87/// @code
88/// BALL_FMT_INFO("Count: {}", ++i); // (!) May or may not be incremented
89/// @endcode
90/// The following `BALL_FMT_*` macros, are the simplest mechanisms to format
91/// (using a standard `format` specification) a single message to a log:
92/// @code
93/// BALL_FMT_TRACE(format_string_literal, ARG1, ARG2, ...);
94/// BALL_FMT_DEBUG(format_string_literal, ARG1, ARG2, ...);
95/// BALL_FMT_INFO( format_string_literal, ARG1, ARG2, ...);
96/// BALL_FMT_WARN( format_string_literal, ARG1, ARG2, ...);
97/// BALL_FMT_ERROR(format_string_literal, ARG1, ARG2, ...);
98/// BALL_FMT_FATAL(format_string_literal, ARG1, ARG2, ...);
99/// @endcode
100/// where `ARG1`, `ARG2`, ... represents any sequence of values for which a
101/// `bsl::format` formatter is defined. The resulting formatted message string
102/// is logged with the severity indicated by the name of the macro (e.g.,
103/// `BALL_FMT_TRACE` logs with severity `ball::Severity::e_TRACE`).
104///
105/// ### Macros for Formatted Logging Inside Code Blocks {#ball_fmt-macros-for-formatted-logging-inside-code-blocks}
106///
107///
108/// `ball_log` provides several kinds of macros to create potentially executed
109/// code blocks from which more complicated logging can be performed. As a
110/// reminder the most commonly used such block macros are:
111/// @code
112/// BALL_LOG_TRACE_BLOCK { ... }
113/// BALL_LOG_DEBUG_BLOCK { ... }
114/// BALL_LOG_INFO_BLOCK { ... }
115/// BALL_LOG_WARN_BLOCK { ... }
116/// BALL_LOG_ERROR_BLOCK { ... }
117/// BALL_LOG_FATAL_BLOCK { ... }
118/// @endcode
119/// Please see `ball_log` for the other such block macros.
120///
121/// Within logging code blocks the special macro, `BALL_FMT` provides
122/// standard `format`-style logging into the log record being built there.
123/// @code
124/// BALL_FMT(format-string-literal, X, Y, ...)
125/// @endcode
126///
127/// ## Usage {#ball_fmt-usage}
128///
129///
130/// The following code fragments illustrate the standard pattern of macro usage.
131///
132/// ### Example 1: A Basic Logging Example {#ball_fmt-example-1-a-basic-logging-example}
133///
134///
135/// The following trivial example shows how to use the logging macros to log
136/// messages at various levels of severity.
137///
138/// First, we initialize the log category within the context of this function.
139/// The logging macros such as `BALL_FMT_ERROR` will not compile unless a
140/// category has been specified in the current lexical scope:
141/// @code
142/// BALL_LOG_SET_CATEGORY("EXAMPLE.CATEGORY");
143/// @endcode
144/// Then, we record messages at various levels of severity. These messages will
145/// be conditionally written to the log depending on the current logging
146/// threshold of the category (configured using the `ball::LoggerManager`
147/// singleton):
148/// @code
149/// BALL_FMT_FATAL("Write this message to the log if the log threshold "
150/// "is above 'ball::Severity::e_FATAL' (i.e., {}).", 32);
151///
152/// BALL_FMT_TRACE("Write this message to the log if the log threshold "
153/// "is above 'ball::Severity::e_TRACE' (i.e., {}).", 192);
154/// @endcode
155/// Next, we demonstrate how to use proprietary code within logging macros.
156/// Suppose you want to add the content of a vector to the log trace:
157/// @code
158/// bsl::vector<int> myVector(4, 328);
159/// BALL_LOG_TRACE_BLOCK {
160/// BALL_FMT("myVector = [ ");
161/// unsigned int position = 0;
162/// for (bsl::vector<int>::const_iterator it = myVector.begin(),
163/// end = myVector.end();
164/// it != end;
165/// ++it, ++position) {
166/// BALL_FMT("{}:{} ", position, *it);
167/// }
168/// BALL_FMT("]");
169/// }
170/// @endcode
171/// Note that the code block will be conditionally executed depending on the
172/// current logging threshold of the category. The code within the block must
173/// not produce any side effects, because its execution depends on the current
174/// logging configuration. The special macro `BALL_FMT` provides the means to
175/// write to the log record from within the block.
176///
177/// ### Example 2: Logging Types with ostream insert operator<< {#ball_fmt-example-2-logging-types-with-ostream-insert-operator}
178///
179///
180/// The following example shows how to use the `bslfmt::streamed` facility with
181/// types that have no support for `bsl::format`ing, but have support for
182/// writing to an `ostream` to facilitate formatted logging.
183///
184/// Suppose we have a type that (we do not own, and) is some sort of identifier
185/// that is capable of "printing" itself to an `ostream`:
186/// @code
187/// namespace abc {
188/// class Identifier {
189/// private:
190/// // DATA
191/// unsigned d_value;
192///
193/// public:
194/// // CREATORS
195/// Identifier(unsigned value) : d_value(value) {}
196///
197/// // ACCESSORS
198/// unsigned value() const { return d_value; }
199/// };
200///
201/// bsl::ostream& operator<<(bsl::ostream& os, const Identifier& obj)
202/// {
203/// return os << obj.value();
204/// }
205///
206/// } // close namespace abc
207/// @endcode
208/// First, we initialize the log category within the context of this function.
209/// The logging macros such as `BALL_FMT_ERROR` will not compile unless a
210/// category has been specified in the current lexical scope:
211/// @code
212/// BALL_LOG_SET_CATEGORY("EXAMPLE.CATEGORY");
213/// @endcode
214/// Then, we record a message containing identifiers using `bslfmt::streamed`:
215/// @code
216/// const abc::Identifier id(12345);
217/// BALL_FMT_FATAL("Item {:>010} does not exist.", bslfmt::streamed(id));
218/// // Logs: `Item 0000012345 does not exist.`
219/// @endcode
220/// Note that the wrapper created by `bslfmt::streamed` uses the `ostream`
221/// insert `operator<<` of `abc::Identifier` to get the characters to print and
222/// uses the syntax of string formatting for the format specification.
223/// @}
224/** @} */
225/** @} */
226
227/** @addtogroup bal
228 * @{
229 */
230/** @addtogroup ball
231 * @{
232 */
233/** @addtogroup ball_fmt
234 * @{
235 */
236
237#include <balscm_version.h>
238
239#include <ball_log.h>
240
241#include <bsl_format.h>
242#include <bsl_iterator.h>
243
244 // =========================
245 // Logging Macro Definitions
246 // =========================
247
248#define BALL_FMT(...) \
249 bsl::format_to( \
250 bsl::ostreambuf_iterator<char>( \
251 &BALL_LOG_RECORD->fixedFields().messageStreamBuf()), \
252 __VA_ARGS__)
253
254#define BALL_FMT_TRACE(...) \
255 BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_TRACE) \
256 BALL_FMT(__VA_ARGS__)
257
258#define BALL_FMT_DEBUG(...) \
259 BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_DEBUG) \
260 BALL_FMT(__VA_ARGS__)
261
262#define BALL_FMT_INFO(...) \
263 BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_INFO) \
264 BALL_FMT(__VA_ARGS__)
265
266#define BALL_FMT_WARN(...) \
267 BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_WARN) \
268 BALL_FMT(__VA_ARGS__)
269
270#define BALL_FMT_ERROR(...) \
271 BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_ERROR) \
272 BALL_FMT(__VA_ARGS__)
273
274#define BALL_FMT_FATAL(...) \
275 BALL_LOG_STREAM_CONST_IMP(BloombergLP::ball::Severity::e_FATAL) \
276 BALL_FMT(__VA_ARGS__)
277
278#endif // INCLUDED_BALL_FMT
279
280// ----------------------------------------------------------------------------
281// Copyright 2025 Bloomberg Finance L.P.
282//
283// Licensed under the Apache License, Version 2.0 (the "License");
284// you may not use this file except in compliance with the License.
285// You may obtain a copy of the License at
286//
287// http://www.apache.org/licenses/LICENSE-2.0
288//
289// Unless required by applicable law or agreed to in writing, software
290// distributed under the License is distributed on an "AS IS" BASIS,
291// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
292// See the License for the specific language governing permissions and
293// limitations under the License.
294// ----------------------------- END-OF-FILE ----------------------------------
295
296/** @} */
297/** @} */
298/** @} */
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238