BDE 4.39.x Production Release
Loading...
Searching...
No Matches
ball_recordformatterregistryutil.h
Go to the documentation of this file.
1/// @file ball_recordformatterregistryutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_recordformatterregistryutil.h -*-C++-*-
8#ifndef INCLUDED_BALL_RECORDFORMATTERREGISTRYUTIL
9#define INCLUDED_BALL_RECORDFORMATTERREGISTRYUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_recordformatterregistryutil ball_recordformatterregistryutil
15/// @brief Provide utilities for creating log record formatters by scheme.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_recordformatterregistryutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_recordformatterregistryutil-purpose"> Purpose</a>
25/// * <a href="#ball_recordformatterregistryutil-classes"> Classes </a>
26/// * <a href="#ball_recordformatterregistryutil-description"> Description </a>
27/// * <a href="#ball_recordformatterregistryutil-behavior-with-invalid-formats"> Behavior with Invalid Formats </a>
28/// * <a href="#ball_recordformatterregistryutil-usage"> Usage </a>
29/// * <a href="#ball_recordformatterregistryutil-example-1-creating-formatters-from-various-scheme-uris"> Example 1: Creating Formatters from Various Scheme URIs </a>
30///
31/// # Purpose {#ball_recordformatterregistryutil-purpose}
32/// Provide utilities for creating log record formatters by scheme.
33///
34/// # Classes {#ball_recordformatterregistryutil-classes}
35///
36/// - ball::RecordFormatterRegistryUtil: utility for formatter creation
37///
38/// @see ball_recordstringformatter, ball_recordjsonformatter
39///
40/// # Description {#ball_recordformatterregistryutil-description}
41/// This component provides a utility `struct`,
42/// `ball::RecordFormatterRegistryUtil`, that defines a namespace for functions
43/// to create log record formatters based on URI-like scheme identifiers. The
44/// primary function, `createRecordFormatter`, interprets a format string
45/// beginning with a scheme (e.g., "text://", "json://", "qjson://") and
46/// delegates to the appropriate specialized formatter factory. This allows
47/// for flexible configuration of log output formats using a single,
48/// scheme-based interface.
49///
50/// The component supports the following schemes:
51/// * **text**: Creates a text-based formatter using
52/// `ball::RecordStringFormatter`
53/// * **json**: Creates a JSON formatter using `ball::RecordJsonFormatter`
54/// * **qjson**: Creates a quoted JSON formatter using
55/// `ball::RecordJsonFormatter`
56///
57/// The scheme determines which formatter will be used and the syntax of the
58/// format specification. The following schemes are currently supported: text,
59/// json, qjson. See [Scheme-Based Formatters](@ref ball-scheme-based-formatters)
60/// for more details of the supported schemes and their accompanying format
61/// specification syntaxes.
62///
63/// ## Behavior with Invalid Formats {#ball_recordformatterregistryutil-behavior-with-invalid-formats}
64///
65///
66/// Trying to create a formatter with an invalid format string or an unknown
67/// scheme will result in a non-zero error code being returned. If the `result`
68/// formatter is not empty the method assumes that it is loaded with a
69/// reasonable (default or otherwise) format and will not change it. In
70/// case `result` is an `empty` `bsl::function` `createRecordFormatter` will
71/// return a non-zero error code and loads a default/fallback formatter into the
72/// `result` parameter. Said fallback formatter will be a sensible default for
73/// the given scheme if the scheme is recognized, or a default/fallback text
74/// formatter if the scheme is not one of the supported ones.
75///
76/// An example with an unknown scheme:
77/// @code
78/// bsl::string unknownScheme = "xml://some-format";
79/// ball::RecordFormatterFunctor::Type fallbackFormatter; // empty formatter
80/// rc = ball::RecordFormatterRegistryUtil::createRecordFormatter(
81/// &fallbackFormatter,
82/// unknownScheme,
83/// options);
84///
85/// assert(0 != rc); // Returns error code for unknown scheme
86/// @endcode
87/// `fallbackFormatter` is still usable as it was loaded with a sensible default
88/// text formatter, allowing the application to continue logging even when the
89/// configuration is incorrect.
90/// @code
91/// bsl::ostringstream fallbackOss;
92/// fallbackFormatter(fallbackOss, record);
93/// assert(!fallbackOss.str().empty()); // Fallback formatter still works:
94/// @endcode
95/// The output of the above code will look something like:
96/// @code
97/// 27AUG2007_16:09:46.161 2040:1 WARN adir/src.cpp:97 CATEGORY Log message\n
98/// @endcode
99/// Currently the text formatter just ignores errors in its format string so
100/// only the "json://" and "qjson://" schemes perform some form of validation.
101/// That means that a meaningless "text://" format will succeed and may not
102/// produce any useful log output, while some invalid "json://" or "qjson://"
103/// formats will fall back to a reasonable default with a non-zero return code.
104/// @code
105/// bsl::string unknownScheme = "test://%73\n";
106/// ball::RecordFormatterFunctor::Type fallbackFormatter; // empty formatter
107/// rc = ball::RecordFormatterRegistryUtil::createRecordFormatter(
108/// &fallbackFormatter,
109/// unknownScheme,
110/// options);
111///
112/// assert(0 == rc); // The text scheme never reports an error
113///
114/// bsl::ostringstream oss;
115/// fallbackFormatter(oss, record);
116/// assert("%73\n" == oss.str()); // Gibberish output due to set format
117/// @endcode
118///
119/// ## Usage {#ball_recordformatterregistryutil-usage}
120///
121///
122/// This section illustrates intended use of this component.
123///
124/// ### Example 1: Creating Formatters from Various Scheme URIs {#ball_recordformatterregistryutil-example-1-creating-formatters-from-various-scheme-uris}
125///
126///
127/// Suppose we have configuration entries that define log record formatters
128/// using URI-like schemes, and we need to create the corresponding formatters.
129/// This component supports "text://", "json://", and "qjson://" schemes.
130///
131/// First, we create formatter options and a test record:
132/// @code
133/// ball::RecordFormatterOptions options(
134/// ball::RecordFormatterTimezone::e_UTC);
135/// ball::Record record = createTestRecord();
136/// @endcode
137/// Now, we demonstrate creating formatters with different schemes. For text
138/// output, we use the "text://" scheme with printf-style format specifiers:
139/// @code
140/// bsl::string textFormat = "text://%d %p:%t %s %f:%l %c %m\n";
141/// ball::RecordFormatterFunctor::Type textFormatter;
142/// int rc = ball::RecordFormatterRegistryUtil::createRecordFormatter(
143/// &textFormatter,
144/// textFormat,
145/// options);
146/// assert(0 == rc);
147/// @endcode
148/// For structured JSON output, we use the "json://" scheme with a JSON array
149/// specifying which fields to include:
150/// @code
151/// bsl::string jsonFormat = "json://[\"tid\",\"severity\",\"message\"]";
152/// ball::RecordFormatterFunctor::Type jsonFormatter;
153/// rc = ball::RecordFormatterRegistryUtil::createRecordFormatter(
154/// &jsonFormatter,
155/// jsonFormat,
156/// options);
157/// assert(0 == rc);
158/// @endcode
159/// For simplified JSON using printf-style specifiers, we use the "qjson://"
160/// scheme:
161/// @code
162/// bsl::string qjsonFormat = "qjson://%i %s %c %m";
163/// ball::RecordFormatterFunctor::Type qjsonFormatter;
164/// rc = ball::RecordFormatterRegistryUtil::createRecordFormatter(
165/// &qjsonFormatter,
166/// qjsonFormat,
167/// options);
168/// assert(0 == rc);
169/// @endcode
170/// Each formatter can then be used to format log records:
171/// @code
172/// bsl::ostringstream textOss, jsonOss, qjsonOss;
173/// textFormatter(textOss, record);
174/// jsonFormatter(jsonOss, record);
175/// qjsonFormatter(qjsonOss, record);
176///
177/// assert(textOss.str().find("Test message") != bsl::string::npos);
178/// assert(jsonOss.str().find("\"message\"") != bsl::string::npos);
179/// assert(qjsonOss.str().find("Test message") != bsl::string::npos);
180/// @endcode
181/// @}
182/** @} */
183/** @} */
184
185/** @addtogroup bal
186 * @{
187 */
188/** @addtogroup ball
189 * @{
190 */
191/** @addtogroup ball_recordformatterregistryutil
192 * @{
193 */
194
195#include <balscm_version.h>
196
199
200#include <bslma_allocator.fwd.h>
201
202#include <bsl_iosfwd.h>
203#include <bsl_string.h>
204#include <bsl_string_view.h>
205
206
207
208namespace ball {
209
210class Record;
211
212 // ==================================
213 // struct RecordFormatterRegistryUtil
214 // ==================================
215
216/// This utility provides a namespace for functions to create log record
217/// formatters based on URI-like scheme identifiers.
218///
219/// See @ref ball_recordformatterregistryutil
221
222 // CONSTANTS
224
225 // CLASS METHODS
226
227 /// Load, into the specified `result` a formatter functor that formats as
228 /// instructed by the specified `format` and `formatOptions`. The `format`
229 /// may start with a URI-like scheme (e.g., `"qjson://"`) that selects both
230 /// the formatter (class) and the syntax of the format specification that
231 /// follows the scheme. In case `format` does not start with a scheme the
232 /// "text://" scheme is assumed. Return 0 if the requested log record
233 /// formatter was successfully created and loaded into `result`.
234 /// Otherwise, if `results is empty, load a default/fallback-formatter into
235 /// `result`, with the requested scheme if that exists or with a sensible
236 /// fallback text log format otherwise. For further details on behavior
237 /// in case of errors see {Behavior with Invalid Formats}. This method
238 /// currently supports the "text", "qjson", and "json" schemes.
241 const bsl::string_view& format,
242 const RecordFormatterOptions& formatOptions);
243};
244
245} // close package namespace
246
247
248#endif // INCLUDED_BALL_RECORDFORMATTERREGISTRYUTIL
249
250// ----------------------------------------------------------------------------
251// Copyright 2025 Bloomberg Finance L.P.
252//
253// Licensed under the Apache License, Version 2.0 (the "License");
254// you may not use this file except in compliance with the License.
255// You may obtain a copy of the License at
256//
257// http://www.apache.org/licenses/LICENSE-2.0
258//
259// Unless required by applicable law or agreed to in writing, software
260// distributed under the License is distributed on an "AS IS" BASIS,
261// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
262// See the License for the specific language governing permissions and
263// limitations under the License.
264// ----------------------------- END-OF-FILE ----------------------------------
265
266/** @} */
267/** @} */
268/** @} */
Definition ball_recordformatteroptions.h:112
Definition bslstl_stringview.h:471
Forward declaration.
Definition bslstl_function.h:946
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition ball_administration.h:214
Definition ball_recordformatterregistryutil.h:220
static int createRecordFormatter(RecordFormatterFunctor::Type *result, const bsl::string_view &format, const RecordFormatterOptions &formatOptions)
static const bsl::string_view k_FALLBACK_LOG_FORMAT_URI
Definition ball_recordformatterregistryutil.h:223