BDE 4.39.x Production Release
Loading...
Searching...
No Matches
ball_fileobserver2.h
Go to the documentation of this file.
1/// @file ball_fileobserver2.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_fileobserver2.h -*-C++-*-
8
9#ifndef INCLUDED_BALL_FILEOBSERVER2
10#define INCLUDED_BALL_FILEOBSERVER2
11
12#include <bsls_ident.h>
13BSLS_IDENT("$Id: $")
14
15/// @defgroup ball_fileobserver2 ball_fileobserver2
16/// @brief Provide a thread-safe observer that emits log records to a file.
17/// @addtogroup bal
18/// @{
19/// @addtogroup ball
20/// @{
21/// @addtogroup ball_fileobserver2
22/// @{
23///
24/// <h1> Outline </h1>
25/// * <a href="#ball_fileobserver2-purpose"> Purpose</a>
26/// * <a href="#ball_fileobserver2-classes"> Classes </a>
27/// * <a href="#ball_fileobserver2-description"> Description </a>
28/// * <a href="#ball_fileobserver2-file-observer-configuration-synopsis"> File Observer Configuration Synopsis </a>
29/// * <a href="#ball_fileobserver2-log-record-formatting"> Log Record Formatting </a>
30/// * <a href="#ball_fileobserver2-scheme-based-format-specifications"> Scheme-Based Format Specifications (Recommended) </a>
31/// * <a href="#ball_fileobserver2-legacy-format-specifications"> Legacy Format Specifications </a>
32/// * <a href="#ball_fileobserver2-log-record-timestamps"> Log Record Timestamps </a>
33/// * <a href="#ball_fileobserver2-local-time-offset-calculations"> Local Time Offset Calculations </a>
34/// * <a href="#ball_fileobserver2-log-filename-patterns"> Log Filename Patterns </a>
35/// * <a href="#ball_fileobserver2-log-file-rotation"> Log File Rotation </a>
36/// * <a href="#ball_fileobserver2-file-rotation-conditions"> File Rotation Conditions </a>
37/// * <a href="#ball_fileobserver2-rotated-file-naming"> Rotated File Naming </a>
38/// * <a href="#ball_fileobserver2-thread-safety"> Thread Safety </a>
39/// * <a href="#ball_fileobserver2-usage"> Usage </a>
40/// * <a href="#ball_fileobserver2-example-basic-usage"> Example: Basic Usage </a>
41///
42/// # Purpose {#ball_fileobserver2-purpose}
43/// Provide a thread-safe observer that emits log records to a file.
44///
45/// # Classes {#ball_fileobserver2-classes}
46///
47/// - ball::FileObserver2: observer that outputs log records to a file
48///
49/// @see ball_record, ball_context, ball_observer,
50/// ball_recordstringformatter
51///
52/// # Description {#ball_fileobserver2-description}
53/// This component provides a concrete implementation of the
54/// `ball::Observer` protocol, `ball::FileObserver2`, for publishing log records
55/// to a user-specified file. The following inheritance hierarchy diagram shows
56/// the classes involved and their methods:
57/// @code
58/// ,-------------------.
59/// ( ball::FileObserver2 )
60/// `-------------------'
61/// | ctor
62/// | disableFileLogging
63/// | disableTimeIntervalRotation
64/// | disableSizeRotation
65/// | disablePublishInLocalTime
66/// | enableFileLogging
67/// | enablePublishInLocalTime
68/// | forceRotation
69/// | rotateOnSize
70/// | rotateOnTimeInterval
71/// | setFormat
72/// | setLogFileFunctor
73/// | setOnFileRotationCallback
74/// | suppressUniqueFileNameOnRotation
75/// | getFormat
76/// | isFileLoggingEnabled
77/// | isPublishInLocalTimeEnabled
78/// | isSuppressUniqueFileNameOnRotation
79/// | rotationLifetime
80/// | rotationSize
81/// V
82/// ,--------------.
83/// ( ball::Observer )
84/// `--------------'
85/// dtor
86/// publish
87/// releaseRecords
88/// @endcode
89/// A `ball::FileObserver2` object processes the log records received through
90/// its `publish` method by writing them to a user-specified file. Note that
91/// the `enableFileLogging` method must be called to enable logging since
92/// logging to a file is initially disabled following construction. The format
93/// of published log records is user-configurable (see {Log Record Formatting}
94/// below). In addition, a file observer may be configured to perform automatic
95/// log file rotation (see {Log File Rotation} below).
96///
97/// ## File Observer Configuration Synopsis {#ball_fileobserver2-file-observer-configuration-synopsis}
98///
99///
100/// `ball::FileObserver2` offers several manipulators that may be used to
101/// configure various aspects of a file observer object. These are summarized
102/// in the following table along with the accessors that can be used to query
103/// the current state of the configuration. Further details are provided in the
104/// following sections and the function-level documentation.
105/// @code
106/// +-------------+------------------------------------+
107/// | Aspect | Related Methods |
108/// +=============+====================================+
109/// | Log Record | setLogFileFunctor |
110/// | Formatting | |
111/// +-------------+------------------------------------+
112/// | Log Record | enablePublishInLocalTime |
113/// | Timestamps | disablePublishInLocalTime |
114/// | | isPublishInLocalTimeEnabled |
115/// +-------------+------------------------------------+
116/// | File | enableFileLogging |
117/// | Logging | disableFileLogging |
118/// | | isFileLoggingEnabled |
119/// +-------------+------------------------------------+
120/// | Log File | rotateOnSize |
121/// | Rotation | rotateOnTimeInterval |
122/// | | disableSizeRotation |
123/// | | disableTimeIntervalRotation |
124/// | | setOnFileRotationCallback |
125/// | | suppressUniqueFileNameOnRotation |
126/// | | rotationSize |
127/// | | rotationLifetime |
128/// | | isSuppressUniqueFileNameOnRotation |
129/// +-------------+------------------------------------+
130/// @endcode
131/// In general, a `ball::FileObserver2` object can be dynamically configured
132/// throughout its lifetime (in particular, before or after being registered
133/// with a logger manager). However, note that for `ball::FileObserver2`,
134/// configuration changes that affect how records are logged (e.g.,
135/// `enablePublishInLocalTime` and `disablePublishInLocalTime`) impact only
136/// those records that are published subsequent to making the configuration
137/// change.
138///
139/// ## Log Record Formatting {#ball_fileobserver2-log-record-formatting}
140///
141///
142/// By default, the output format of published log records is:
143/// @code
144/// DATE_TIME PID:THREAD-ID SEVERITY FILE:LINE CATEGORY MESSAGE USER-FIELDS
145/// @endcode
146/// where `DATE` and `TIME` are of the form `DDMonYYYY` and `HH:MM:SS.mmm`,
147/// respectively (`Mon` being the 3-letter abbreviation for the month). For
148/// example, a log record will have the following appearance when the default
149/// format is in effect (assuming that no user-defined fields are present):
150/// @code
151/// 18MAY2005_18:58:12.076 7959:1 WARN ball_fileobserver2.t.cpp:404 TEST hello!
152/// @endcode
153/// For additional flexibility, the `setFormat` method can be called to
154/// configure the format of published records to the file. The format
155/// specifications can be either scheme-tagged (recommended) or legacy
156/// `printf`-style format strings that results in a `RecordStringFormatter`
157/// being used.
158///
159/// ### Scheme-Based Format Specifications (Recommended) {#ball_fileobserver2-scheme-based-format-specifications}
160///
161///
162/// The recommended way to specify log record formats is using URI-like
163/// scheme-tagged format configuration strings. A scheme-tagged format string
164/// begins with a scheme identifier followed by `://` and then a
165/// scheme-specific format specification:
166/// @code
167/// <scheme>://<format-specification>
168/// @endcode
169/// The scheme determines which formatter will be used and the syntax of the
170/// format specification. The following schemes are currently supported: text,
171/// json, qjson. See [Scheme-Based Formatters](@ref ball-scheme-based-formatters)
172/// for more details of the supported schemes and their accompanying format
173/// specification syntaxes.
174///
175/// For example, to log records to a file in JSON format with printf-style
176/// format specification:
177/// @code
178/// fileObserver2.setFormat("qjson://%d %p:%t %s %f:%l %c %m");
179/// @endcode
180///
181/// ### Legacy Format Specifications {#ball_fileobserver2-legacy-format-specifications}
182///
183///
184/// For backward compatibility, format specifications that do not begin with a
185/// scheme tag are treated as legacy `printf`-style format strings. Such
186/// specifications are implicitly treated as if they had a `text://` prefix
187/// and use `ball::RecordStringFormatter`. For example, the following two
188/// calls are equivalent:
189/// @code
190/// fileObserver2.setFormat("%d %p:%t %s %f:%l %c %m %a\n");
191/// fileObserver2.setFormat("text://%d %p:%t %s %f:%l %c %m %a\n");
192/// @endcode
193/// These `%`-prefixed conversion specifications are defined in
194/// @ref ball_recordstringformatter .
195///
196/// ## Log Record Timestamps {#ball_fileobserver2-log-record-timestamps}
197///
198///
199/// By default, the timestamp attributes of published records are written in UTC
200/// time. To write timestamps in local time instead, call the
201/// `enablePublishInLocalTime` method. Note that the local time offset is
202/// calculated using the UTC timestamp of each record. To revert to UTC time,
203/// call the `disablePublishInLocalTime` method. Whether UTC time or local time
204/// is in effect can be queried via `isPublishInLocalTimeEnabled`. However,
205/// note that if the user installs a log record formatting functor via
206/// `setLogFileFunctor`, then the supplied functor determines how record
207/// timestamps are rendered to the log.
208///
209/// ### Local Time Offset Calculations {#ball_fileobserver2-local-time-offset-calculations}
210///
211///
212/// The calculation of the local time offset adds some overhead to the
213/// publication of each log record. If this overhead is an issue, it can be
214/// mitigated by installing a high-performance local-time offset callback for
215/// `bdlt::CurrentTime` in `main`. See @ref bsls_systemtime for the details of
216/// installing such a callback and see @ref baltzo_localtimeoffsetutil for an
217/// example facility. Note that such callbacks can improve performance for all
218/// users of `bdlt::CurrentTime`, not just the `ball` logger.
219///
220/// ## Log Filename Patterns {#ball_fileobserver2-log-filename-patterns}
221///
222///
223/// The `enableFileLogging` method supports the use of `%`-escape sequences to
224/// specify log filenames. The recognized sequences are as follows:
225/// @code
226/// %Y - current year (4 digits with leading zeros)
227/// %M - current month (2 digits with leading zeros)
228/// %D - current day (2 digits with leading zeros)
229/// %h - current hour (2 digits with leading zeros)
230/// %m - current minute (2 digits with leading zeros)
231/// %s - current second (2 digits with leading zeros)
232/// %T - current datetime, equivalent to "%Y%M%D_%h%m%s"
233/// %p - process ID
234/// @endcode
235/// The date and time elements of the derived filename are based on the time
236/// when the log file is created. Furthermore, these elements are based on
237/// either UTC time or local time depending on the value returned by
238/// `isPublishInLocalTimeEnabled`. (See {Log Record Timestamps} for the
239/// similarity with the treatment of record timestamps.)
240///
241/// For example, a log filename pattern of "task.log.%Y%M%D_%h%m%s" will yield
242/// the filename `task.log.20110501_123000` if the file is created on
243/// 01-May-2011 at 12:30:00 local time (assuming `enablePublishInLocalTime` was
244/// called).
245///
246/// ## Log File Rotation {#ball_fileobserver2-log-file-rotation}
247///
248///
249/// A `ball::FileObserver2` may be configured to perform automatic rotation of
250/// log files based on simple file rotation conditions (or rules).
251///
252/// ### File Rotation Conditions {#ball_fileobserver2-file-rotation-conditions}
253///
254///
255/// Rotation rules may be established based on the size of the log file (i.e., a
256/// "rotation-on-size" rule), and a periodic time interval (i.e., a
257/// "rotation-on-time-interval" rule). These rules are independently enabled by
258/// the `rotateOnSize` and `rotateOnTimeInterval` methods, respectively. If
259/// both rules are in effect, log file rotation is performed whenever either
260/// rule applies.
261///
262/// ### Rotated File Naming {#ball_fileobserver2-rotated-file-naming}
263///
264///
265/// When a log file is rotated, a new filename is generated using the pattern
266/// supplied to `enableFileLogging`. If the file having the new name does not
267/// exist, the current log file is closed, and the logging continues to the new
268/// file.
269///
270/// If the file having the new name already exits, then the behavior of the file
271/// rotation is further controlled by the flag set with
272/// `suppressUniqueFileNameOnRotation`:
273///
274/// * `suppressUniqueFileNameOnRotation(false)` (*default* behavior)
275/// The current log filename is renamed by appending a timestamp in the form
276/// ".%Y%M%D_%h%m%s" where the timestamp indicates when the file being
277/// rotated was last opened (the time of either the last file rotation or the
278/// last call to `enableFileLogging`, whichever is most recent). As with the
279/// timestamps of logged records, the timestamps appended to log filenames
280/// upon rotation will be in UTC time or local time depending on the value
281/// returned by `isPublishInLocalTimeEnabled`.
282/// * `suppressUniqueFileNameOnRotation(true)`
283/// The logging continues to the *current* log file, effectively suppressing
284/// log filename rotation. This may happen when the log file pattern does
285/// not contain %-escape sequences indicating a time period, or the rotation
286/// interval is less than the time period encoded by %-escape sequences. In
287/// order to rotate log files in this mode, the log file pattern MUST contain
288/// %-escape sequences that specify date and (optionally) time. For example,
289/// the log filename pattern "app_%Y%M%D.log" will produce a single log file
290/// per calendar day (assuming, the rotation on time is enabled and the
291/// rotation happens at least once a day).
292///
293/// The two tables below illustrate the names of old and new log files when a
294/// file rotation occurs. We assume that the log file is rotated on 2011-May-21
295/// at 12:29:59 local time and that the last rotation occurred at 12:30:00 on
296/// the previous day. We further assume that `enablePublishInLocalTime` was
297/// called, so that all date and time elements are rendered in local time.
298///
299/// The first table shows the name change (if any) of the (old) log file being
300/// rotated when the flag controlled by `suppressUniqueFileNameOnRotation`
301/// is set to `false`:
302/// @code
303/// Disabled: `suppressUniqueFileNameOnRotation`
304///
305/// For brevity:
306/// <TS1> = 20210520_123000
307/// <TS2> = 20210521_122959 (aka next day, about the same time)
308///
309/// +----------------+-----------------+----------------+----------------------
310/// | Pattern | Filename Before | Filename After | Rotated Filename
311/// | | Rotation | Rotation |
312/// +----------------+-----------------+----------------+----------------------
313/// | "a.log" | a.log | a.log | a.log.<TS1>
314/// | "a.log.%T" | a.log.<TS1> | a.log.<TS2> | a.log.<TS1>
315/// | "a.log.%Y%M" | a.log.202105 | a.log.202105 | a.log.202105.<TS1>
316/// | "a.log.%Y%M%D" | a.log.20210520 | a.log.20110521 | a.log.20210520
317/// +----------------+-----------------+----------------+----------------------
318/// @endcode
319/// Note that upon rotation a timestamp was appended to the name of the rotated
320/// file when the log pattern does not contain %-escape sequences indicating a
321/// time period ("a.log"), or the rotation period (in our case, one day) is less
322/// than the time period encoded in the pattern (in case of "a.log.%Y%M" the
323/// period is one month).
324///
325/// The next table shows the rotated name when the flag controlled by
326/// `suppressUniqueFileNameOnRotation` is set to `true`, and (possibly new) name
327/// of the (new) log file following rotation:
328/// @code
329/// Enabled: `suppressUniqueFileNameOnRotation`
330///
331/// +----------------+-----------------+----------------+----------------------
332/// | Pattern | Filename Before | Filename After | Rotated Filename
333/// | | Rotation | Rotation |
334/// +----------------+-----------------+----------------+----------------------
335/// | "a.log" | a.log | a.log | none
336/// | "a.log.%T" | a.log.<TS1> | a.log.<TS2> | a.log.<TS1>
337/// | "a.log.%Y%M" | a.log.202105 | a.log.202105 | none
338/// | "a.log.%Y%M%D" | a.log.20210520 | a.log.20110521 | a.log.20210520
339/// +----------------+-----------------+----------------+----------------------
340/// @endcode
341/// Note that the original filename is reused when the log pattern does not
342/// contain %-escape sequences indicating a time period ("a.log"), or the
343/// rotation period (in our case, one day) is less than the time period encoded
344/// in the pattern (in case of "a.log.%Y%M" the period is one month).
345///
346/// Also note, that in any cases, when the log pattern includes "%T", or encodes
347/// a time period that coincides the rotation period (in case of "a.log.%Y%M%D"
348/// the period is one day), then a unique name on each rotation is produced with
349/// the (local) time at which file rotation occurred embedded in the filename.
350///
351/// ## Thread Safety {#ball_fileobserver2-thread-safety}
352///
353///
354/// All methods of `ball::FileObserver2` are thread-safe, and can be called
355/// concurrently by multiple threads.
356///
357/// ## Usage {#ball_fileobserver2-usage}
358///
359///
360/// This section illustrates intended use of this component.
361///
362/// ### Example: Basic Usage {#ball_fileobserver2-example-basic-usage}
363///
364///
365/// First, we create a `ball::LoggerManagerConfiguration` object, `lmConfig`,
366/// and set the logging "pass-through" level -- the level at which log records
367/// are published to registered observers -- to `DEBUG`:
368/// @code
369/// int main()
370/// {
371/// ball::LoggerManagerConfiguration lmConfig;
372/// lmConfig.setDefaultThresholdLevelsIfValid(ball::Severity::e_DEBUG);
373/// @endcode
374/// Next, create a `ball::LoggerManagerScopedGuard` object whose constructor
375/// takes the configuration object just created. The guard will initialize the
376/// logger manager singleton on creation and destroy the singleton upon
377/// destruction. This guarantees that any resources used by the logger manager
378/// will be properly released when they are not needed:
379/// @code
380/// ball::LoggerManagerScopedGuard guard(lmConfig);
381/// ball::LoggerManager& manager = ball::LoggerManager::singleton();
382/// @endcode
383/// Next, we create a `ball::FileObserver2` object and register it with the
384/// `ball` logging system;
385/// @code
386/// bsl::shared_ptr<ball::FileObserver2> observer =
387/// bsl::make_shared<ball::FileObserver2>();
388/// @endcode
389/// Next, we configure the log file rotation rules:
390/// @code
391/// // Rotate the file when its size becomes greater than or equal to 128
392/// // megabytes.
393/// observer->rotateOnSize(1024 * 128);
394///
395/// // Rotate the file every 24 hours.
396/// observer->rotateOnTimeInterval(bdlt::DatetimeInterval(1));
397/// @endcode
398/// Note that in this configuration the user may end up with multiple log files
399/// for a specific day (because of the rotation-on-size rule).
400///
401/// Then, we enable logging to a file:
402/// @code
403/// // Create and log records to a file named "/var/log/task/task.log".
404/// observer->enableFileLogging("/var/log/task/task.log");
405/// @endcode
406/// Finally, we register the file observer with the logger manager. Upon
407/// successful registration, the observer will start to receive log records via
408/// the `publish` method:
409/// @code
410/// int rc = manager.registerObserver(observer, "default");
411/// assert(0 == rc);
412/// return 0;
413/// }
414/// @endcode
415/// @}
416/** @} */
417/** @} */
418
419/** @addtogroup bal
420 * @{
421 */
422/** @addtogroup ball
423 * @{
424 */
425/** @addtogroup ball_fileobserver2
426 * @{
427 */
428
429#include <balscm_version.h>
430
432#include <ball_observer.h>
434#include <ball_severity.h>
435
436#include <bdls_fdstreambuf.h>
437
438#include <bdlt_datetime.h>
440
441#include <bsla_deprecated.h>
442
443#include <bslma_allocator.h>
445
447
448#include <bslmt_mutex.h>
449
450#include <bsls_keyword.h>
451#include <bsls_libraryfeatures.h>
452
453#include <bsl_fstream.h>
454#include <bsl_functional.h>
455#include <bsl_iosfwd.h>
456#include <bsl_memory.h>
457#include <bsl_string.h>
458
459#include <string> // `std::string`, `std::pmr::string`
460
461
462namespace ball {
463
464class Context;
465class Record;
466
467 // ===================
468 // class FileObserver2
469 // ===================
470
471/// This class implements the `Observer` protocol. The `publish` method of
472/// this class outputs the log records that it receives to a user-specified
473/// file. This class is thread-safe; different threads can operate on an
474/// object concurrently. This class is exception-neutral with no guarantee
475/// of rollback. In no event is memory leaked.
476///
477/// See @ref ball_fileobserver2
478class FileObserver2 : public Observer {
479
480 public:
481 // PUBLIC TYPES
482
483 /// `RecordFormatter` is an alias for the type of the functor used for
484 /// formatting log records to a stream.
487
488 /// `OnFileRotationCallback` is an alias for a user-supplied callback
489 /// function that is invoked after the file observer attempts to rotate
490 /// its log file. The callback takes two arguments: (1) an integer
491 /// status value where 0 indicates a new log file was successfully
492 /// created and a non-zero value indicates an error occurred during
493 /// rotation, and (2) a string that provides the name of the rotated log
494 /// file if the rotation was successful. E.g.:
495 /// @code
496 /// void onLogFileRotation(int rotationStatus,
497 /// const bsl::string& rotatedLogFileName);
498 /// @endcode
499 typedef bsl::function<void(int, const bsl::string&)>
501
502 private:
503 // DATA
504 bdls::FdStreamBuf d_logStreamBuf; // stream buffer for
505 // file logging
506
507 bsl::ostream d_logOutStream; // output stream for
508 // file logging (refers
509 // to `d_logStreamBuf`)
510
511 bsl::string d_logFilePattern; // log filename pattern
512
513 bsl::string d_logFileName; // current log filename
514
515 bdlt::Datetime d_logFileTimestampUtc; // modification time of
516 // the log file when it
517 // was opened (or the
518 // creation time if the
519 // log file did not
520 // already exist)
521
522 ObserverFormatterImp d_observerFormatterImp; // formatter manager
523 // that handles all
524 // formatting operations
525
526 bool d_suppressUniqueFileName; // `false` if rotated
527 // log file has a unique
528 // name
529
530 mutable bslmt::Mutex d_mutex; // serialize operations
531
532 int d_rotationSize; // maximum log file size
533 // before rotation (in
534 // kilobytes)
535
536 bdlt::Datetime d_rotationReferenceTime; // reference start time
537 // (time-zone determined
538 // by
539 // d_publishInLocalTime)
540 // for time-based
541 // rotation
542
543 bdlt::DatetimeInterval d_rotationInterval; // time interval between
544 // two time-based
545 // rotations
546
547 bdlt::Datetime d_nextRotationTimeUtc; // next scheduled time
548 // for time-based
549 // rotation
550
551 OnFileRotationCallback d_onRotationCb; // user callback
552 // invoked following
553 // file rotation
554
555 mutable bslmt::Mutex d_rotationCbMutex; // serialize access to
556 // 'd_onRotationCb';
557 // required because
558 // callback must be
559 // called with 'd_mutex'
560 // unlocked
561
562 private:
563 // NOT IMPLEMENTED
565 FileObserver2& operator=(const FileObserver2&);
566
567 private:
568 // PRIVATE MANIPULATORS
569
570 /// Perform a log file rotation by closing the current log file of this
571 /// file observer, renaming the closed log file if necessary, and
572 /// opening a new log file. Load, into the specified
573 /// `rotatedLogFileName`, the name of the rotated log file. Return 0 on
574 /// success, a positive value if logging is not enabled, and a negative
575 /// value otherwise. The existing log file is renamed if the new log
576 /// filename, as determined by the `logFilenamePattern` of the latest
577 /// call to `enableFileLogging`, is the same as the old log filename.
578 int rotateFile(bsl::string *rotatedLogFileName);
579
580 /// Perform log file rotation if the specified `currentLogTimeUtc` is
581 /// later than the scheduled rotation time of the current log file, or
582 /// if the log file is larger than the allowable size, and if a rotation
583 /// is performed, load into the specified `rotatedLogFileName` the name
584 /// of the rotated file. Return 0 if the log file is rotated
585 /// successfully, a positive value if a rotation was determined to be
586 /// unnecessary, and a negative value otherwise. The rotation schedule
587 /// and the allowable file size are set by the `rotateOnTimeInterval`
588 /// and the `rotateOnSize` methods, respectively.
589 ///
590 /// \pre The behavior is undefined unless the caller acquired the lock for this object.
591 int rotateIfNecessary(bsl::string *rotatedLogFileName,
592 const bdlt::Datetime& currentLogTimeUtc);
593
594 // PRIVATE ACCESSORS
595
596 /// Return `true` if file logging is enabled for this file observer, and
597 /// `false` otherwise. Load the specified `result` with the name of the
598 /// current log file if file logging is enabled, and leave `result`
599 /// unmodified otherwise.
600 template <class t_STRING>
601 bool isFileLoggingEnabledImpl(t_STRING *result) const;
602
603 public:
604 // TRAITS
606
607 // CREATORS
608
609 /// Create a file observer with file logging initially disabled.
610 /// Optionally specify a `basicAllocator` used to supply memory. If
611 /// `basicAllocator` is 0, the currently installed default allocator is used.
612 ///
613 /// \note Note that `isPublishInLocalTimeEnabled` returns `false`
614 /// following construction indicating that the timestamp attribute of
615 /// published records will be written in UTC time (see
616 /// `enablePublishInLocalTime`). Also note that a default record format
617 /// is in effect for file logging (see `setLogFileFunctor`).
618 explicit FileObserver2(bslma::Allocator *basicAllocator = 0);
619
620 /// Close the log file of this file observer if file logging is enabled,
621 /// and destroy this file observer.
623
624 // MANIPULATORS
625
626 /// Disable file logging for this file observer. This method has no effect if file logging is not enabled.
627 ///
628 /// \note Note that records
629 /// subsequently received through the `publish` method will be dropped
630 /// until file logging is re-enabled.
632
633 /// Disable log file rotation based on a periodic time interval for this
634 /// file observer. This method has no effect if
635 /// rotation-on-time-interval is not enabled.
636 ///
637 /// @deprecated Use @ref disableTimeIntervalRotation instead.
639
640 /// Disable publishing of the timestamp attribute of records in local
641 /// time by this file observer; henceforth, timestamps will be in UTC
642 /// time. This method has no effect if publishing in local time is not enabled.
643 ///
644 /// \note Note that this method also affects log filenames (see {Log
645 /// Filename Patterns}).
647
648 /// Disable log file rotation based on log file size for this file
649 /// observer. This method has no effect if rotation-on-size is not
650 /// enabled.
652
653 /// Disable log file rotation based on a periodic time interval for this
654 /// file observer. This method has no effect if
655 /// rotation-on-time-interval is not enabled.
657
658 /// Enable logging of all records published to this file observer to a
659 /// file whose name is derived from the specified `logFilenamePattern`.
660 /// Return 0 on success, a positive value if file logging is already
661 /// enabled (with no effect), and a negative value otherwise. The
662 /// basename of `logFilenamePattern` may contain `%`-escape sequences
663 /// that are interpreted as follows:
664 /// @code
665 /// %Y - current year (4 digits with leading zeros)
666 /// %M - current month (2 digits with leading zeros)
667 /// %D - current day (2 digits with leading zeros)
668 /// %h - current hour (2 digits with leading zeros)
669 /// %m - current minute (2 digits with leading zeros)
670 /// %s - current second (2 digits with leading zeros)
671 /// %T - current datetime, equivalent to "%Y%M%D_%h%m%s"
672 /// %p - process ID
673 /// @endcode
674 /// Each time a log file is opened by this file observer (upon a
675 /// successful call to this method and following each log file
676 /// rotation), the name of the new log file is derived from
677 /// `logFilenamePattern` by interpreting the above recognized `%`-escape
678 /// sequences. If `isPublishInLocalTimeEnabled` returns `true`, the
679 /// `%`-escape sequences related to time will be substituted with local
680 /// time values, and UTC time values otherwise. See {Log Filename
681 /// Patterns}.
682 int enableFileLogging(const char *logFilenamePattern);
683
684 /// Enable logging of all records published to this file observer to a
685 /// file whose name is derived from the specified `logFilenamePattern`
686 /// and append a timestamp to the log filename if the specified
687 /// `appendTimestampFlag` is `true`. Return 0 on success, a positive
688 /// value if file logging is already enabled (with no effect), and a
689 /// negative value otherwise. If the `appendTimestampFlag` is `true`
690 /// and `logFilenamePattern` does not contain any `%`-escape sequences,
691 /// this method behaves as if ".%T" is appended to `logFilenamePattern`.
692 ///
693 /// @deprecated Use @ref enableFileLogging(logFilenamePattern) instead
694 /// (use the ".%T" pattern to replicate `true == appendTimestampFlag`
695 /// behavior).
696 int enableFileLogging(const char *logFilenamePattern,
697 bool appendTimestampFlag);
698
699 /// Enable publishing of the timestamp attribute of records in local
700 /// time by this file observer. This method has no effect if publishing in local time is already enabled.
701 ///
702 /// \note Note that this method also
703 /// affects log filenames (see {Log Filename Patterns}).
705
706 /// Process the specified log `record` having the specified publishing
707 /// `context` by writing `record` and `context` to the current log file
708 /// if file logging is enabled for this file observer. The method has
709 /// no effect if file logging is not enabled, in which case `record` is
710 /// dropped.
711 ///
712 /// @deprecated Do not use.
713 void publish(const Record& record,
714 const Context& context) BSLS_KEYWORD_OVERRIDE;
715
716 /// Process the record referenced by the specified `record` shared
717 /// pointer having the specified publishing `context` by writing the
718 /// record and `context` to the current log file if file logging is
719 /// enabled for this file observer. The method has no effect if file
720 /// logging is not enabled, in which case `record` is dropped.
721 void publish(const bsl::shared_ptr<const Record>& record,
722 const Context& context)
724
725 /// Discard any shared references to `Record` objects that were supplied
726 /// to the `publish` method, and are held by this observer.
727 ///
728 /// \note Note that this operation should be called if resources underlying the
729 /// previously provided shared pointers must be released.
731
732 /// Forcefully perform a log file rotation by this file observer. Close
733 /// the current log file, rename the log file if necessary, and open a
734 /// new log file. This method has no effect if file logging is not
735 /// enabled. See {Rotated File Naming} for details on filenames of
736 /// rotated log files.
738
739 /// Set this file observer to perform log file rotation when the size of
740 /// the file exceeds the specified `size` (in kilobytes). This rule
741 /// replaces any rotation-on-size rule currently in effect.
742 ///
743 /// \pre The behavior is undefined unless `size > 0`.
744 void rotateOnSize(int size);
745
746 /// Set this file observer to perform a periodic log file rotation at
747 /// multiples of the specified `timeInterval`. This rule replaces any
748 /// rotation-on-time-interval rule currently in effect.
749 ///
750 /// \pre The behavior is undefined unless `0 < timeInterval.totalMilliseconds()`.
751 ///
752 /// @deprecated Use @ref rotateOnTimeInterval instead.
753 void rotateOnLifetime(const bdlt::DatetimeInterval& timeInterval);
754
755 /// Set this file observer to perform a periodic log file rotation at
756 /// multiples of the specified `interval`. Optionally specify a
757 /// `startTime` indicating the datetime to use as the starting point for
758 /// computing the periodic rotation schedule. If
759 /// `isPublishInLocalTimeEnabled` is `true`, the `startTime` is
760 /// interpreted as local time, and as a UTC time otherwise. If
761 /// `startTime` is not specified, the current time is used. This rule
762 /// replaces any rotation-on-time-interval rule currently in effect.
763 ///
764 /// \pre The behavior is undefined unless `0 < interval.totalMilliseconds()`.
765 ///
766 /// \note Note that `startTime` may be a fixed time in the past; e.g., a
767 /// reference time of `bdlt::Datetime(1, 1, 1)` and an interval of 24
768 /// hours would configure a periodic rotation at midnight each day.
769 void rotateOnTimeInterval(const bdlt::DatetimeInterval& interval);
770 void rotateOnTimeInterval(const bdlt::DatetimeInterval& interval,
771 const bdlt::Datetime& startTime);
772
773 /// Set the formatting functor used when writing records to the log file of this file observer to the specified `logFileFunctor`.
774 ///
775 /// \note Note that a
776 /// default format ("\n%d %p:%t %s %f:%l %c %m %u\n") is in effect until
777 /// this method or `setFormat` is called. Also, notice that the observer
778 /// emits newline characters at the beginning and at the end of a log
779 /// record by default, so the user needs to add them explicitly to (text)
780 /// format strings to preserve that behavior.
781 ///
782 /// \note Note that this method exists for backwards compatibility and new code is
783 /// highly encouraged to make use of `setFormat` with the URI-scheme-like
784 /// tags to create different formatters. (Currently string and JSON output
785 /// format is supported.)
786 void setLogFileFunctor(const RecordFormatter& logFileFunctor);
787
788 /// Set the formatting functor used when writing records to the log file
789 /// of this file observer to a log file functor created according to the
790 /// specified, possibly URI-like scheme tagged, `format`. Return zero if
791 /// the setup with the specified arguments was successful and also save
792 /// the `format` to be later retrievable using `getFormat`. Otherwise (if
793 /// no matching scheme could be found or the configuration is invalid)
794 /// return a non-zero value and do not change the log record formatter used by this object.
795 ///
796 /// \note Note that a default format
797 /// ("\n%d %p:%t %s %f:%l %c %m %u\n") is in effect until this method or
798 /// `setLogFileFunctor` is called. Also, notice that the observer emits
799 /// newline characters at the beginning and at the end of a log record by
800 /// default, so the user needs to add them explicitly to (text) format
801 /// strings to preserve that behavior.
802 int setFormat(const bsl::string_view& format);
803
804 /// Set the specified `onRotationCallback` to be invoked after each time
805 /// this file observer attempts to perform a log file rotation.
806 ///
807 /// \pre The behavior is undefined if the supplied function calls either
808 /// `setOnFileRotationCallback`, `forceRotation`, or `publish` on this
809 /// file observer (i.e., the supplied callback should *not* attempt to
810 /// write to the `ball` log).
812 const OnFileRotationCallback& onRotationCallback);
813
814 /// Suppress generating a unique log file name upon rotation if the
815 /// specified `suppress` is `true`, and generate a unique filename
816 /// otherwise. See {Rotated File Naming} for details.
818
819 // ACCESSORS
820
821 /// Return `true` if file logging is enabled for this file observer, and
822 /// `false` otherwise. Load the optionally specified `result` with the
823 /// name of the current log file if file logging is enabled, and leave `result` unmodified otherwise.
824 ///
825 /// \note Note that records received through
826 /// the `publish` method of this file observer will be dropped when this
827 /// method returns `false`.
829 bool isFileLoggingEnabled(bsl::string *result) const;
830 bool isFileLoggingEnabled(std::string *result) const;
831
832#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
833 /// Return `true` if file logging is enabled for this file observer, and
834 /// `false` otherwise. Load the specified `result` with the name of the
835 /// current log file if file logging is enabled, and leave `result`
836 /// unmodified otherwise.
837 bool isFileLoggingEnabled(std::pmr::string *result) const;
838#endif // BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
839
840 /// Return `true` if this file observer writes the timestamp attribute
841 /// of records that it publishes in local time, and `false` otherwise (in which case timestamps are written in UTC time).
842 ///
843 /// \note Note that the
844 /// value returned by this method also affects log filenames (see {Log
845 /// Filename Patterns}).
847
848 /// Return `true` if the log filename uniqueness check on rotation is
849 /// suppressed, and false otherwise.
851
852 /// Return the format config of the last successful `setFormat` call.
853 const bsl::string& getFormat() const;
854
855 /// Return the lifetime of the log file that will trigger a file
856 /// rotation by this file observer if rotation-on-lifetime is in effect,
857 /// and a 0 time interval otherwise.
859
860 /// Return the size (in kilobytes) of the log file that will trigger a
861 /// file rotation by this file observer if rotation-on-size is in
862 /// effect, and 0 otherwise.
863 int rotationSize() const;
864
865 /// Return the difference between the local time and UTC time in effect when this file observer was constructed.
866 ///
867 /// \note Note that this value
868 /// remains unchanged during the lifetime of this object and therefore
869 /// may become incorrect when the difference between the local time and
870 /// UTC time changes (e.g., when transitioning into or out of daylight
871 /// savings time).
872 ///
873 /// @deprecated Use @ref bdlt::LocalTimeOffset instead.
875};
876
877// ============================================================================
878// INLINE DEFINITIONS
879// ============================================================================
880
881 // -------------------
882 // class FileObserver2
883 // -------------------
884
885// MANIPULATORS
886inline
887void FileObserver2::publish(const Record& record, const Context& context)
888{
889 // It is safe to create a shared_ptr with a custom deleter that does
890 // nothing because we know exactly the publish method we delegate to, and
891 // that it does not store the `shared_ptr` beyond the lifetime of the call.
893
894 // Delegate to the other overload which then immediately publishes the
895 // record, and does not store the `shared_ptr` to extend its lifetime.
896 publish(ptr, context);
897}
898
899inline
903
904} // close package namespace
905
906
907#endif
908
909// ----------------------------------------------------------------------------
910// Copyright 2015 Bloomberg Finance L.P.
911//
912// Licensed under the Apache License, Version 2.0 (the "License");
913// you may not use this file except in compliance with the License.
914// You may obtain a copy of the License at
915//
916// http://www.apache.org/licenses/LICENSE-2.0
917//
918// Unless required by applicable law or agreed to in writing, software
919// distributed under the License is distributed on an "AS IS" BASIS,
920// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
921// See the License for the specific language governing permissions and
922// limitations under the License.
923// ----------------------------- END-OF-FILE ----------------------------------
924
925/** @} */
926/** @} */
927/** @} */
Definition ball_context.h:297
Definition ball_fileobserver2.h:478
void rotateOnSize(int size)
bsl::function< void(int, const bsl::string &)> OnFileRotationCallback
Definition ball_fileobserver2.h:500
void rotateOnTimeInterval(const bdlt::DatetimeInterval &interval)
bool isSuppressUniqueFileNameOnRotation() const
bdlt::DatetimeInterval rotationLifetime() const
bdlt::DatetimeInterval localTimeOffset() const
void disablePublishInLocalTime()
RecordFormatterFunctor::Type RecordFormatter
Definition ball_fileobserver2.h:485
void rotateOnLifetime(const bdlt::DatetimeInterval &timeInterval)
void releaseRecords() BSLS_KEYWORD_OVERRIDE
Definition ball_fileobserver2.h:900
bool isFileLoggingEnabled() const
void disableLifetimeRotation()
int rotationSize() const
void disableTimeIntervalRotation()
~FileObserver2() BSLS_KEYWORD_OVERRIDE
void enablePublishInLocalTime()
void publish(const Record &record, const Context &context) BSLS_KEYWORD_OVERRIDE
Definition ball_fileobserver2.h:887
RecordFormatterFunctor::Type LogRecordFunctor
Definition ball_fileobserver2.h:486
void setOnFileRotationCallback(const OnFileRotationCallback &onRotationCallback)
int enableFileLogging(const char *logFilenamePattern)
const bsl::string & getFormat() const
Return the format config of the last successful setFormat call.
BSLMF_NESTED_TRAIT_DECLARATION(FileObserver2, bslma::UsesBslmaAllocator)
bool isPublishInLocalTimeEnabled() const
void setLogFileFunctor(const RecordFormatter &logFileFunctor)
int setFormat(const bsl::string_view &format)
FileObserver2(bslma::Allocator *basicAllocator=0)
void suppressUniqueFileNameOnRotation(bool suppress)
Definition ball_observerformatterimp.h:398
Definition ball_observer.h:235
Definition ball_record.h:176
Definition bdls_fdstreambuf.h:671
Definition bdlt_datetimeinterval.h:201
Definition bdlt_datetime.h:330
Definition bslstl_string.h:1252
Forward declaration.
Definition bslstl_function.h:946
Definition bslstl_sharedptr.h:1838
Definition bslma_allocator.h:545
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 bbldc_basicisma30360.h:112
Definition bdlat_valuetypefunctions.h:939
Definition bdldfp_decimal.h:5549
Definition bslma_usesbslmaallocator.h:344
Definition bslstl_sharedptr.h:4289