BDE 4.39.x Production Release
Loading...
Searching...
No Matches
ball_cstdioobserver.h
Go to the documentation of this file.
1/// @file ball_cstdioobserver.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_cstdioobserver.h -*-C++-*-
8#ifndef INCLUDED_BALL_CSTDIOOBSERVER
9#define INCLUDED_BALL_CSTDIOOBSERVER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_cstdioobserver ball_cstdioobserver
15/// @brief Provide an observer that emits log records to a `FILE *`.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_cstdioobserver
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_cstdioobserver-purpose"> Purpose</a>
25/// * <a href="#ball_cstdioobserver-classes"> Classes </a>
26/// * <a href="#ball_cstdioobserver-description"> Description </a>
27/// * <a href="#ball_cstdioobserver-log-record-formatting"> Log Record Formatting </a>
28/// * <a href="#ball_cstdioobserver-scheme-based-format-specifications"> Scheme-Based Format Specifications (Recommended) </a>
29/// * <a href="#ball_cstdioobserver-legacy-format-specifications"> Legacy Format Specifications </a>
30/// * <a href="#ball_cstdioobserver-thread-safety"> Thread Safety </a>
31/// * <a href="#ball_cstdioobserver-usage"> Usage </a>
32/// * <a href="#ball_cstdioobserver-example-1-basic-usage"> Example 1: Basic Usage </a>
33///
34/// # Purpose {#ball_cstdioobserver-purpose}
35/// Provide an observer that emits log records to a `FILE *`.
36///
37/// # Classes {#ball_cstdioobserver-classes}
38///
39/// - ball::CstdioObserver: observer that emits log records to a `FILE *`
40///
41/// @see ball_record, ball_context, ball_loggermanager
42///
43/// # Description {#ball_cstdioobserver-description}
44/// This component provides a concrete implementation of the
45/// `ball::Observer` protocol for receiving and processing log records:
46/// @code
47/// ,--------------------.
48/// ( ball::CstdioObserver )
49/// `--------------------'
50/// | ctor
51/// | disablePublishInLocalTime
52/// | enablePublishInLocalTime
53/// | setFormat
54/// | setFormatFunctor
55/// | getFormat
56/// | isPublishInLocalTimeEnabled
57/// V
58/// ,--------------.
59/// ( ball::Observer )
60/// `--------------'
61/// publish
62/// releaseRecords
63/// dtor
64/// @endcode
65/// `ball::CstdioObserver` is a concrete class derived from `ball::Observer`
66/// that processes the log records it receives through its `publish` method by
67/// writing them to a C `stdio` output file (`FILE *`). Given its minimal
68/// functionality, `ball::CstdioObserver` should be used with care in a
69/// production environment. It is not recommended to construct this observer
70/// with file-based streams due to lack of any file rotation functionality,
71/// however it is ideal for writing to `stdout` or `stderr`.
72///
73/// ## Log Record Formatting {#ball_cstdioobserver-log-record-formatting}
74///
75///
76/// By default, the output format of published log records is:
77/// @code
78/// DATE_TIME PID THREAD-ID SEVERITY FILE LINE CATEGORY MESSAGE USER-FIELDS
79/// @endcode
80/// where `DATE` and `TIME` are of the form `DDMonYYYY` and `HH:MM:SS.mmm`,
81/// respectively (`Mon` being the 3-letter abbreviation for the month). For
82/// example, assuming that no user-defined fields are present, a log record
83/// will have the following appearance when the default format is in effect:
84/// @code
85/// 18MAY2005_18:58:12.076 7959 1 WARN ball_cstdioobserver.t.cpp 404 TEST hi!
86/// @endcode
87/// The default format and the formatter used can be changed by calling the
88/// `setFormat` method. The format specifications can be either scheme-tagged
89/// (recommended) or legacy format strings that results in a
90/// `RecordStringFormatter` being used. See {Scheme-Based Format Specifications
91/// (Recommended)} and {Legacy Format Specifications}.
92/// @code
93/// streamObserver.setFormat("qjson://%d %s %m");
94/// @endcode
95/// The above statement will cause subsequent records to be logged as JSON
96/// objects that contain a timestamp in 'DDMonYYYY_HH:MM:SS.mmm' format, the
97/// severity, and the log message.
98///
99/// ### Scheme-Based Format Specifications (Recommended) {#ball_cstdioobserver-scheme-based-format-specifications}
100///
101///
102/// The log record format can be specified using a URI-like scheme-tagged
103/// format configuration string passed to the `setFormat` method. The scheme
104/// determines which formatter will be used:
105///
106/// * text://<format-specification>
107/// > Uses `ball::RecordStringFormatter` with the provided format
108/// > specification. For example:
109/// > `"text://\n%d %p:%t %s %f:%l %c %m %a\n"`
110///
111/// * qjson://<format-specification>
112/// > Uses `ball::RecordJsonFormatter` to output log records in JSON format
113/// > using a simplified printf-style format specification. The format
114/// > specification uses `%`-prefixed fields (e.g., `"%d"` for timestamp,
115/// > `"%s"` for severity, `"%m"` for message). For example:
116/// > `"qjson://%d %s %m"`. See @ref ball_recordjsonformatter for the complete
117/// > list of supported `%` fields.
118///
119/// * json://<format-specification>
120/// > Uses `ball::RecordJsonFormatter` to output log records in JSON format.
121/// > The format specification must be a JSON array (using `[]` brackets)
122/// > listing the field names to include in the output. For example:
123/// > `json://["timestamp","severity","message"]`. See
124/// > @ref ball_recordjsonformatter for details on supported field names and
125/// > format specifications.
126///
127/// Examples:
128/// @code
129/// // Use JSON formatter with simplified printf-style format specification
130/// streamObserver.setFormat("qjson://%d %s %m");
131///
132/// // Use text formatter with custom format
133/// streamObserver.setFormat("text://%d %p %t %s %f %l %c %m %a\n");
134///
135/// // Use JSON formatter with selected fields
136/// streamObserver.setFormat("json://[\"timestamp\",\"severity\",\"message\"]");
137/// @endcode
138///
139/// ### Legacy Format Specifications {#ball_cstdioobserver-legacy-format-specifications}
140///
141///
142/// If no scheme is specified (i.e., the configuration doesn't contain `://`),
143/// the configuration is treated as a format specification for
144/// `ball::RecordStringFormatter` (equivalent to `text://`). The `%`-prefixed
145/// conversion specifications for the "text://" format are defined in
146/// @ref ball_recordstringformatter .
147///
148/// Note that the observer's default text format emits newline characters at the
149/// beginning and at the end of a log record, so the user needs to add them
150/// explicitly to (text) format strings to preserve that behavior.
151///
152/// There is also a legacy way to override the default format by supplying a
153/// suitable formatting functor using `setFormatFunctor`. For example, an
154/// instance of `ball::RecordStringFormatter` is such a functor:
155/// @code
156/// ball::CstdioObserver streamObserver(stdout);
157/// streamObserver.setFormatFunctor(
158/// ball::RecordStringFormatter("%I %p:%t %s %f:%l %c %m %a\n"));
159/// @endcode
160/// The above statement will cause subsequent records to be logged in a format
161/// that is almost identical to the default format except that the timestamp
162/// attribute will be written in ISO 8601 format, and the user fields will be
163/// replaced by the more modern attributes.
164///
165/// Example using format specification directly (no scheme):
166/// @code
167/// // Backward compatible: no scheme means text format
168/// streamObserver.setFormat("%d %p %t %s %f %l %c %m %a\n");
169/// @endcode
170///
171/// ## Thread Safety {#ball_cstdioobserver-thread-safety}
172///
173///
174/// All methods of `ball::CstdioObserver` are thread-safe, and can be called
175/// concurrently by multiple threads.
176///
177/// ## Usage {#ball_cstdioobserver-usage}
178///
179///
180/// This section illustrates intended use of this component.
181///
182/// ### Example 1: Basic Usage {#ball_cstdioobserver-example-1-basic-usage}
183///
184///
185/// The following snippets of code illustrate the basic usage of
186/// `ball::CstdioObserver`.
187///
188/// First create a `ball::Record` object `record` and a `ball::Context` object
189/// `context`. Note that the default values for these objects (or their
190/// contained objects) are perfectly suitable for logging purposes.
191/// @code
192/// ball::RecordAttributes attributes;
193/// ball::UserFields fieldValues;
194/// ball::Context context;
195///
196/// bslma::Allocator *ga = bslma::Default::globalAllocator(0);
197/// const bsl::shared_ptr<const ball::Record>
198/// record(new (*ga) ball::Record(attributes, fieldValues, ga), ga);
199/// @endcode
200/// Next, create a cstdio observer `observer` with the `stdout` as the output
201/// stream.
202/// @code
203/// ball::CstdioObserver observer(stdout);
204/// @endcode
205/// Finally, publish `record` and `context` to `observer`.
206/// @code
207/// observer.publish(record, context);
208/// @endcode
209/// This will produce the following output on `stdout`:
210/// @code
211/// 01JAN0001_24:00:00.000 0 0 OFF 0
212/// @endcode
213/// @}
214/** @} */
215/** @} */
216
217/** @addtogroup bal
218 * @{
219 */
220/** @addtogroup ball
221 * @{
222 */
223/** @addtogroup ball_cstdioobserver
224 * @{
225 */
226
227#include <balscm_version.h>
228
230#include <ball_observer.h>
233
234#include <bsla_deprecated.h>
235
236#include <bslma_allocator.h>
237#include <bslma_bslallocator.h>
239
241
242#include <bslmt_mutex.h>
243
244#include <bsls_assert.h>
245#include <bsls_keyword.h>
246#include <bsls_review.h>
247
248#include <bsl_cstdio.h>
249#include <bsl_functional.h>
250
251
252namespace ball {
253
254class Context;
255class Record;
256
257 // ====================
258 // class CstdioObserver
259 // ====================
260
261/// This class provides a concrete implementation of the `Observer`
262/// protocol. The `publish` method of this class outputs the log records
263/// that it receives to a `FILE *` supplied at construction and then flushes
264/// the stream.
265///
266/// See @ref ball_cstdioobserver
267class CstdioObserver : public Observer {
268 public:
269 // TYPES
270
271 /// `LogRecordFunctor` is an alias for the type of the functor used for
272 /// formatting log records to a stream.
274
276
277 private:
278 // PRIVATE TYPES
280
281 private:
282 // DATA
283 FILE *d_file_p; // output sink for log
284 // records
285
286 mutable bslmt::Mutex d_mutex; // serializes concurrent
287 // calls to 'publish'
288
289 ObserverFormatterImp d_observerFormatterImp;
290 // formatter manager that
291 // handles all formatting
292 // operations
293
294 private:
295 // NOT IMPLEMENTED
297 CstdioObserver& operator=(const CstdioObserver&);
298
299 public:
300 // TRAITS
302
303 // CREATORS
304
305 /// Create a cstdio observer that transmits log records to the specified
306 /// `stream`. Optionally specify an `allocator` (e.g., the address of a
307 /// `bslma::Allocator` object) to supply memory; otherwise, the default allocator is used.
308 ///
309 /// \note Note that a default record format is in effect
310 /// for cstdio logging (see `setFormat`).
311 explicit
312 CstdioObserver(FILE *stream,
313 const allocator_type& allocator = allocator_type());
314
315 /// Destroy this cstdio observer.
317
318 // MANIPULATORS
319
320 using Observer::publish; // Picks up the deprecated `publish` overload.
321
322 /// Process the specified log `record` having the specified publishing
323 /// `context`. Print `record` and `context` to the `FILE *` supplied at construction.
324 ///
325 /// \pre The behavior is undefined if `record` or `context`
326 /// is modified during the execution of this method.
327 void publish(const bsl::shared_ptr<const Record>& record,
328 const Context& context)
330
331 /// Discard any shared reference to a `Record` object that was supplied
332 /// to the `publish` method, and is held by this observer.
333 ///
334 /// \note Note that this operation should be called if resources underlying the
335 /// previously provided shared-pointers must be released. This method
336 /// intentionally does nothing as no such resources are held; we publish
337 /// all records immediately.
339
340 /// Disable publishing of the timestamp attribute of records in local
341 /// time by this cstdio observer; henceforth, timestamps will be in UTC
342 /// time. This method has no effect if publishing in local time is not
343 /// enabled.
345
346 /// Enable publishing of the timestamp attribute of records in local
347 /// time by this cstdio observer. By default, timestamps are published in UTC time.
348 ///
349 /// \note Note that this method also affects timestamps for
350 /// formatters that use them.
352
353 /// Set the formatting functor used when writing records to the log of
354 /// this cstdio observer to the specified `formatter` functor.
355 ///
356 /// \note Note that a default format ("\n%d %p %t %s %f %l %c %m %u\n") is in
357 /// effect until this method or `setFormat` is called (see
358 /// @ref ball_recordstringformatter ). Also note that the observer emits
359 /// newline characters at the beginning and at the end of a log record
360 /// by default, so the user needs to add them explicitly to the format string to preserve this behavior.
361 ///
362 /// \note Note that this method is not
363 /// able to communicate the timezone default settings to the
364 /// `formatter`, prefer `setFormat`.
365 void setFormatFunctor(const RecordFormatter& formatter);
366
367 /// Set the formatting functor used when writing records to the log of
368 /// this cstdio observer to a functor created according to the specified,
369 /// possibly URI-like, scheme-tagged `format`. Return zero if the setup
370 /// with the specified arguments was successful and also save the `format`
371 /// to be later retrievable using `getFormat`. Otherwise (if no matching
372 /// scheme could be found or the configuration is invalid) return a
373 /// non-zero value and do not change the log record formatter used by this object.
374 ///
375 /// \note Note that a default format
376 /// ("\n%d %p %t %s %f %l %c %m %u\n") is in effect until this method or
377 /// `setFormatFunctor` is called. Also, notice that the observer emits
378 /// newline characters at the beginning and at the end of a log record by
379 /// (the) default (format), so the user needs to add them explicitly to
380 /// (text) format strings to preserve that behavior.
381 int setFormat(const bsl::string_view& format);
382
383 // ACCESSORS
384
385 /// Return `true` if this observer writes the timestamp attribute of
386 /// records that it publishes in local time by default, and `false`
387 /// otherwise (in which case timestamps are written by default in UTC time).
389
390 /// Return the format config of the last successful `setFormat` call.
391 const bsl::string& getFormat() const;
392};
393
394// ============================================================================
395// INLINE DEFINITIONS
396// ============================================================================
397
398 // --------------------
399 // class CstdioObserver
400 // --------------------
401
402// MANIPULATORS
403inline
407
408} // close package namespace
409
410
411#endif
412
413// ----------------------------------------------------------------------------
414// Copyright 2025 Bloomberg Finance L.P.
415//
416// Licensed under the Apache License, Version 2.0 (the "License");
417// you may not use this file except in compliance with the License.
418// You may obtain a copy of the License at
419//
420// http://www.apache.org/licenses/LICENSE-2.0
421//
422// Unless required by applicable law or agreed to in writing, software
423// distributed under the License is distributed on an "AS IS" BASIS,
424// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
425// See the License for the specific language governing permissions and
426// limitations under the License.
427// ----------------------------- END-OF-FILE ----------------------------------
428
429/** @} */
430/** @} */
431/** @} */
Definition ball_context.h:297
Definition ball_cstdioobserver.h:267
bsl::allocator< char > allocator_type
Definition ball_cstdioobserver.h:275
RecordFormatterFunctor::Type RecordFormatter
Definition ball_cstdioobserver.h:273
const bsl::string & getFormat() const
Return the format config of the last successful setFormat call.
void setFormatFunctor(const RecordFormatter &formatter)
void publish(const bsl::shared_ptr< const Record > &record, const Context &context) BSLS_KEYWORD_OVERRIDE
void releaseRecords() BSLS_KEYWORD_OVERRIDE
Definition ball_cstdioobserver.h:404
void disablePublishInLocalTime()
BSLMF_NESTED_TRAIT_DECLARATION(CstdioObserver, bslma::UsesBslmaAllocator)
void enablePublishInLocalTime()
~CstdioObserver() BSLS_KEYWORD_OVERRIDE
Destroy this cstdio observer.
int setFormat(const bsl::string_view &format)
CstdioObserver(FILE *stream, const allocator_type &allocator=allocator_type())
bool isPublishInLocalTimeEnabled() const
Definition ball_observerformatterimp.h:398
Definition ball_observer.h:235
Definition ball_record.h:176
Definition bslma_bslallocator.h:588
Forward declaration.
Definition bslstl_function.h:946
Definition bslmt_mutex.h:317
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:695
Definition ball_administration.h:214
Definition bdlat_valuetypefunctions.h:939
Enum
Timezone setting for timestamps in log record formatters.
Definition ball_recordformattertimezone.h:114
Definition bslma_usesbslmaallocator.h:344