BDE 4.14.0 Production release
Loading...
Searching...
No Matches
ball_asyncfileobserver.h
Go to the documentation of this file.
1/// @file ball_asyncfileobserver.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_asyncfileobserver.h -*-C++-*-
8#ifndef INCLUDED_BALL_ASYNCFILEOBSERVER
9#define INCLUDED_BALL_ASYNCFILEOBSERVER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_asyncfileobserver ball_asyncfileobserver
15/// @brief Provide an asynchronous observer that logs to a file and `stdout`.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_asyncfileobserver
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_asyncfileobserver-purpose"> Purpose</a>
25/// * <a href="#ball_asyncfileobserver-classes"> Classes </a>
26/// * <a href="#ball_asyncfileobserver-description"> Description </a>
27/// * <a href="#ball_asyncfileobserver-async-file-observer-configuration-synopsis"> Async File Observer Configuration Synopsis </a>
28/// * <a href="#ball_asyncfileobserver-log-record-queue"> Log Record Queue </a>
29/// * <a href="#ball_asyncfileobserver-log-record-formatting"> Log Record Formatting </a>
30/// * <a href="#ball_asyncfileobserver-log-record-timestamps"> Log Record Timestamps </a>
31/// * <a href="#ball_asyncfileobserver-local-time-offset-calculations"> Local Time Offset Calculations </a>
32/// * <a href="#ball_asyncfileobserver-log-filename-patterns"> Log Filename Patterns </a>
33/// * <a href="#ball_asyncfileobserver-log-file-rotation"> Log File Rotation </a>
34/// * <a href="#ball_asyncfileobserver-file-rotation-conditions"> File Rotation Conditions </a>
35/// * <a href="#ball_asyncfileobserver-rotated-file-naming"> Rotated File Naming </a>
36/// * <a href="#ball_asyncfileobserver-thread-safety"> Thread Safety </a>
37/// * <a href="#ball_asyncfileobserver-usage"> Usage </a>
38/// * <a href="#ball_asyncfileobserver-example-1-publication-through-the-logger-manager"> Example 1: Publication Through the Logger Manager </a>
39///
40/// # Purpose {#ball_asyncfileobserver-purpose}
41/// Provide an asynchronous observer that logs to a file and `stdout`.
42///
43/// # Classes {#ball_asyncfileobserver-classes}
44///
45/// - ball::AsyncFileObserver: observer that outputs logs to a file and `stdout`
46///
47/// @see ball_record, ball_context, ball_observer, ball_fileobserver
48///
49/// # Description {#ball_asyncfileobserver-description}
50/// This component provides a concrete implementation of the
51/// `ball::Observer` protocol, `ball::AsyncFileObserver`, for *asynchronously*
52/// publishing log records to `stdout` and, optionally, to a user-specified
53/// file. A `ball::AsyncFileObserver` (informally, "async file observer")
54/// object processes the log records received through its `publish` method by
55/// pushing the supplied `ball::Record` object onto a queue and (typically)
56/// returning immediately (see {Log Record Queue}). Each enqueued record is
57/// ultimately published when an independent publication thread removes the log
58/// record from the queue and writes it to the configured log file and `stdout`.
59/// The following inheritance hierarchy diagram shows the classes involved and
60/// their methods:
61/// @code
62/// ,-----------------------.
63/// ( ball::AsyncFileObserver )
64/// `-----------------------'
65/// | ctor
66/// | disableFileLogging
67/// | disablePublishInLocalTime
68/// | disableSizeRotation
69/// | disableStdoutLoggingPrefix
70/// | disableTimeIntervalRotation
71/// | enableFileLogging
72/// | enableStdoutLoggingPrefix
73/// | enablePublishInLocalTime
74/// | forceRotation
75/// | rotateOnSize
76/// | rotateOnTimeInterval
77/// | setLogFormat
78/// | setOnFileRotationCallback
79/// | setStdoutThreshold
80/// | shutdownPublicationThread
81/// | startPublicationThread
82/// | stopPublicationThread
83/// | suppressUniqueFileNameOnRotation
84/// | getLogFormat
85/// | isFileLoggingEnabled
86/// | isPublicationThreadRunning
87/// | isPublishInLocalTimeEnabled
88/// | isStdoutLoggingPrefixEnabled
89/// | isSuppressUniqueFileNameOnRotation
90/// | recordQueueLength
91/// | rotationLifetime
92/// | rotationSize
93/// | stdoutThreshold
94/// V
95/// ,--------------.
96/// ( ball::Observer )
97/// `--------------'
98/// dtor
99/// publish
100/// releaseRecords
101/// @endcode
102/// The format of published log records is user-configurable for both logging to
103/// `stdout` and logging to a file (see {Log Record Formatting} below).
104/// Although logging to a file is initially disabled following construction, the
105/// most common use-case for `ball::AsyncFileObserver` is to also log to a file,
106/// enabled by calling the `enableFileLogging` method. In addition, an async
107/// file observer may be configured to perform automatic log file rotation (see
108/// {Log File Rotation} below).
109///
110/// ## Async File Observer Configuration Synopsis {#ball_asyncfileobserver-async-file-observer-configuration-synopsis}
111///
112///
113/// `ball::AsyncFileObserver` offers several constructor arguments and
114/// manipulators that may be used to configure various aspects of an async file
115/// observer object. These are summarized in the following tables along with
116/// the accessors that can be used to query the current state of the
117/// configuration. Further details are provided in the following sections and
118/// the function-level documentation.
119/// @code
120/// +-----------------------+---------------------------------+
121/// | Aspect | Constructor Arguments |
122/// +=======================+=================================+
123/// | Log Record Timestamps | publishInLocalTime |
124/// +-----------------------+---------------------------------+
125/// | 'stdout' Logging | stdoutThreshold |
126/// +-----------------------+---------------------------------+
127/// | Log Record Queue | maxRecordQueueSize |
128/// | | dropRecordsOnFullQueueThreshold |
129/// +-----------------------+---------------------------------+
130///
131/// +-------------+------------------------------------+
132/// | Aspect | Related Methods |
133/// +=============+====================================+
134/// | Log Record | setLogFormat |
135/// | Formatting | enableStdoutLoggingPrefix |
136/// | | disableStdoutLoggingPrefix |
137/// | | getLogFormat |
138/// | | isStdoutLoggingPrefixEnabled |
139/// +-------------+------------------------------------+
140/// | Log Record | enablePublishInLocalTime |
141/// | Timestamps | disablePublishInLocalTime |
142/// | | isPublishInLocalTimeEnabled |
143/// +-------------+----------------------------------- +
144/// | File | enableFileLogging |
145/// | Logging | disableFileLogging |
146/// | | isFileLoggingEnabled |
147/// +-------------+----------------------------------- +
148/// | 'stdout' | setStdoutThreshold |
149/// | Logging | enableStdoutLoggingPrefix |
150/// | | disableStdoutLoggingPrefix |
151/// | | stdoutThreshold |
152/// | | isStdoutLoggingPrefixEnabled |
153/// +-------------+------------------------------------+
154/// | Log File | rotateOnSize |
155/// | Rotation | rotateOnTimeInterval |
156/// | | disableSizeRotation |
157/// | | disableTimeIntervalRotation |
158/// | | setOnFileRotationCallback |
159/// | | suppressUniqueFileNameOnRotation |
160/// | | rotationSize |
161/// | | rotationLifetime |
162/// | | isSuppressUniqueFileNameOnRotation |
163/// +-------------+------------------------------------+
164/// | Publication | startPublicationThread |
165/// | Thread | stopPublicationThread |
166/// | Management | shutdownPublicationThread |
167/// | | isPublicationThreadRunning |
168/// +-------------+------------------------------------+
169/// @endcode
170/// In general, a `ball::AsyncFileObserver` object can be dynamically configured
171/// throughout its lifetime (in particular, before or after being registered
172/// with a logger manager). Note that for `ball::AsyncFileObserver`,
173/// configuration changes that affect how records are logged (e.g.,
174/// `enablePublishInLocalTime` and `disablePublishInLocalTime`) impact both
175/// those records received by the `publish` method subsequent to making the
176/// configuration change as well as those records that are already on the queue.
177///
178/// ## Log Record Queue {#ball_asyncfileobserver-log-record-queue}
179///
180///
181/// The log record queue of an async file observer has a configurable, but
182/// fixed, maximum size, where the default is 8192. The `maxRecordQueueSize`
183/// constructor argument may be used to specify an alternative maximum size for
184/// the record queue that can be either larger or smaller than the default.
185///
186/// By default, an async file observer is configured for the `publish` method to
187/// drop *all* records that it receives while the queue is full. This behavior
188/// can be modified by supplying a `Severity::Level` for the constructor
189/// argument `dropRecordsOnFullQueueThreshold` whereby only those records whose
190/// severity is less severe than that threshold are dropped. Each record whose
191/// severity is at least as severe as `dropRecordsOnFullQueueThreshold` will
192/// cause the `publish` method to *block* until the queue has spare capacity to
193/// accommodate the record (presumably freed up by the publication thread having
194/// consumed a record from the queue). For example, if this threshold is set to
195/// `e_WARN` on construction, `e_INFO`, `e_DEBUG`, and `e_TRACE` records are
196/// dropped by `publish` when the queue is full whereas `e_WARN`, `e_ERROR`, and
197/// `e_FATAL` records will cause `publish` to block while waiting for room in
198/// the queue. Note that while `publish` will never block with the default
199/// threshold setting, clients should consider the trade-offs between dropping
200/// potentially critical log messages versus possibly blocking in `publish` on
201/// such messages.
202///
203/// An async file observer maintains a count of the records that are dropped,
204/// periodically publishing a warning (i.e., an internally generated log record
205/// with severity `e_WARN`) that reports the number of dropped records. The
206/// record count is reset to 0 after each such warning is published, so each
207/// dropped record is counted only once.
208///
209/// ## Log Record Formatting {#ball_asyncfileobserver-log-record-formatting}
210///
211///
212/// By default, the output format of published log records (whether to `stdout`
213/// or a user-specified file) is:
214/// @code
215/// DATE_TIME PID:THREAD-ID SEVERITY FILE:LINE CATEGORY MESSAGE USER-FIELDS
216/// @endcode
217/// where `DATE` and `TIME` are of the form `DDMonYYYY` and `HH:MM:SS.mmm`,
218/// respectively (`Mon` being the 3-letter abbreviation for the month). For
219/// example, assuming that no user-defined fields are present, a log record
220/// will have the following appearance when the default format is in effect:
221/// @code
222/// 18MAY2005_18:58:12.076 7959:1 WARN ball_asyncfileobserver.t.cpp:404 TEST hi
223/// @endcode
224/// The default format for records published to `stdout` (only) can be shortened
225/// by calling `disableStdoutLoggingPrefix`. This method has the effect of
226/// reducing the above example message to the following when output to `stdout`:
227/// @code
228/// WARN ball_asyncfileobserver.t.cpp:404 TEST hi
229/// @endcode
230/// For additional flexibility, the `setLogFormat` method can be called to
231/// configure the format of published records. This method takes two arguments:
232/// one specifies the format of records logged to `stdout` and the other applies
233/// to records that are logged to a file. The respective formats are specified
234/// using `printf`-style (`%`-prefixed) conversion specifications. (See
235/// @ref ball_recordstringformatter for information on how format specifications
236/// are defined and interpreted.) For example, the following statement will
237/// force subsequent records to be logged in a format that is almost identical
238/// to the default long format except that the timestamp attribute will be
239/// written in ISO 8601 format:
240/// @code
241/// asyncFileObserver.setLogFormat("\n%I %p:%t %s %f:%l %c %m %u\n",
242/// "\n%I %p:%t %s %f:%l %c %m %u\n");
243/// @endcode
244/// Once a customized format is specified for `stdout`, calling
245/// `disableStdoutLoggingPrefix` will switch to the default short format, i.e.,
246/// "\n%s %f:%l %c %m %u\n". If `enableStdoutLoggingPrefix` is subsequently
247/// called, the customized format specified in the most recent call to
248/// `setLogFormat` will be reinstated.
249///
250/// Note that the observer emits newline characters at the beginning and at the
251/// end of a log record by default, so the user needs to add them explicitly to
252/// the format string to preserve this behavior.
253///
254/// Also note that in the sample long-form message above the timestamp has
255/// millisecond precision (`18MAY2005_18:58:12.076`). If microsecond precision
256/// is desired instead, consider using either the `%D` or `%O` format
257/// specification supported by @ref ball_recordstringformatter .
258///
259/// ## Log Record Timestamps {#ball_asyncfileobserver-log-record-timestamps}
260///
261///
262/// By default, the timestamp attributes of published records are written in UTC
263/// time (unless `true` is supplied for the optional `publishInLocalTime`
264/// constructor flag). To write timestamps in local time instead, call the
265/// `enablePublishInLocalTime` method. Note that the local time offset is
266/// calculated using the UTC timestamp of each record. To revert to UTC time,
267/// call the `disablePublishInLocalTime` method. Whether UTC time or local time
268/// is in effect can be queried via `isPublishInLocalTimeEnabled`.
269///
270/// Note that log record timestamps that are output (to either `stdout` or to a
271/// file) reflect the times at which the records were received by the `publish`
272/// method of the async file observer (and pushed onto the queue). That is, the
273/// length of time that a record resides on the queue does not impact the
274/// record's timestamp when it is eventually output by the publication thread.
275///
276/// ### Local Time Offset Calculations {#ball_asyncfileobserver-local-time-offset-calculations}
277///
278///
279/// The calculation of the local time offset adds some overhead to the
280/// publication of each log record. If this overhead is an issue, it can be
281/// mitigated by installing a high-performance local-time offset callback for
282/// `bdlt::CurrentTime` in `main`. See @ref bsls_systemtime for the details of
283/// installing such a callback and see @ref baltzo_localtimeoffsetutil for an
284/// example facility. Note that such callbacks can improve performance for all
285/// users of `bdlt::CurrentTime`, not just the `ball` logger.
286///
287/// ## Log Filename Patterns {#ball_asyncfileobserver-log-filename-patterns}
288///
289///
290/// The `enableFileLogging` method supports the use of `%`-escape sequences to
291/// specify log filenames. The recognized sequences are as follows:
292/// @code
293/// %Y - current year (4 digits with leading zeros)
294/// %M - current month (2 digits with leading zeros)
295/// %D - current day (2 digits with leading zeros)
296/// %h - current hour (2 digits with leading zeros)
297/// %m - current minute (2 digits with leading zeros)
298/// %s - current second (2 digits with leading zeros)
299/// %T - current datetime, equivalent to "%Y%M%D_%h%m%s"
300/// %p - process ID
301/// @endcode
302/// The date and time elements of the derived filename are based on the time
303/// when the log file is created. Furthermore, these elements are based on
304/// either UTC time or local time depending on the value returned by
305/// `isPublishInLocalTimeEnabled`. (See {Log Record Timestamps} for the
306/// similarity with the treatment of record timestamps.)
307///
308/// For example, a log filename pattern of "task.log.%Y%M%D_%h%m%s" will yield
309/// the filename `task.log.20110501_123000` if the file is created on
310/// 01-May-2011 at 12:30:00 local time (assuming `enablePublishInLocalTime` was
311/// called).
312///
313/// ## Log File Rotation {#ball_asyncfileobserver-log-file-rotation}
314///
315///
316/// A `ball::AsyncFileObserver` may be configured to perform automatic rotation
317/// of log files based on simple file rotation conditions (or rules).
318///
319/// ### File Rotation Conditions {#ball_asyncfileobserver-file-rotation-conditions}
320///
321///
322/// Rotation rules may be established based on the size of the log file (i.e., a
323/// "rotation-on-size" rule), and a periodic time interval (i.e., a
324/// "rotation-on-time-interval" rule). These rules are independently enabled by
325/// the `rotateOnSize` and `rotateOnTimeInterval` methods, respectively. If
326/// both rules are in effect, log file rotation is performed whenever either
327/// rule applies.
328///
329/// ### Rotated File Naming {#ball_asyncfileobserver-rotated-file-naming}
330///
331///
332/// When a log file is rotated, a new filename is generated using the pattern
333/// supplied to `enableFileLogging`. If the file having the new name does not
334/// exist, the current log file is closed, and the logging continues to the new
335/// file.
336///
337/// If the file having the new name already exits, then the behavior of the file
338/// rotation is further controlled by the flag set with
339/// `suppressUniqueFileNameOnRotation`:
340///
341/// * `suppressUniqueFileNameOnRotation(false)` (*default* behavior)
342/// The current log filename is renamed by appending a timestamp in the form
343/// ".%Y%M%D_%h%m%s" where the timestamp indicates when the file being
344/// rotated was last opened (the time of either the last file rotation or the
345/// last call to `enableFileLogging`, whichever is most recent). As with the
346/// timestamps of logged records, the timestamps appended to log filenames
347/// upon rotation will be in UTC time or local time depending on the value
348/// returned by `isPublishInLocalTimeEnabled`.
349/// * `suppressUniqueFileNameOnRotation(true)`
350/// The logging continues to the *current* log file, effectively suppressing
351/// log filename rotation. This may happen when the log file pattern does
352/// not contain %-escape sequences indicating a time period, or the rotation
353/// interval is less than the time period encoded by %-escape sequences. In
354/// order to rotate log files in this mode, the log file pattern MUST contain
355/// %-escape sequences that specify date and (optionally) time. For example,
356/// the log filename pattern "app_%Y%M%D.log" will produce a single log file
357/// per calendar day (assuming, the rotation on time is enabled and the
358/// rotation happens at least once a day).
359///
360/// The two tables below illustrate the names of old and new log files when a
361/// file rotation occurs. We assume that the log file is rotated on 2011-May-21
362/// at 12:29:59 local time and that the last rotation occurred at 12:30:00 on
363/// the previous day. We further assume that `enablePublishInLocalTime` was
364/// called, so that all date and time elements are rendered in local time.
365///
366/// The first table shows the name change (if any) of the (old) log file being
367/// rotated when the flag controlled by `suppressUniqueFileNameOnRotation`
368/// is set to `false`:
369/// @code
370/// Disabled: 'suppressUniqueFileNameOnRotation'
371///
372/// For brevity:
373/// <TS1> = 20210520_123000
374/// <TS2> = 20210521_122959 (aka next day, about the same time)
375///
376/// +----------------+-----------------+----------------+----------------------
377/// | Pattern | Filename Before | Filename After | Rotated Filename
378/// | | Rotation | Rotation |
379/// +----------------+-----------------+----------------+----------------------
380/// | "a.log" | a.log | a.log | a.log.<TS1>
381/// | "a.log.%T" | a.log.<TS1> | a.log.<TS2> | a.log.<TS1>
382/// | "a.log.%Y%M" | a.log.202105 | a.log.202105 | a.log.202105.<TS1>
383/// | "a.log.%Y%M%D" | a.log.20210520 | a.log.20110521 | a.log.20210520
384/// +----------------+-----------------+----------------+----------------------
385/// @endcode
386/// Note that upon rotation a timestamp was appended to the name of the rotated
387/// file when the log pattern does not contain %-escape sequences indicating a
388/// time period ("a.log"), or the rotation period (in our case, one day) is less
389/// than the time period encoded in the pattern (in case of "a.log.%Y%M" the
390/// period is one month).
391///
392/// The next table shows the rotated name when the flag controlled by
393/// `suppressUniqueFileNameOnRotation` is set to `true`, and (possibly new) name
394/// of the (new) log file following rotation:
395/// @code
396/// Enabled: 'suppressUniqueFileNameOnRotation'
397///
398/// +----------------+-----------------+----------------+----------------------
399/// | Pattern | Filename Before | Filename After | Rotated Filename
400/// | | Rotation | Rotation |
401/// +----------------+-----------------+----------------+----------------------
402/// | "a.log" | a.log | a.log | none
403/// | "a.log.%T" | a.log.<TS1> | a.log.<TS2> | a.log.<TS1>
404/// | "a.log.%Y%M" | a.log.202105 | a.log.202105 | none
405/// | "a.log.%Y%M%D" | a.log.20210520 | a.log.20110521 | a.log.20210520
406/// +----------------+-----------------+----------------+----------------------
407/// @endcode
408/// Note that the original filename is reused when the log pattern does not
409/// contain %-escape sequences indicating a time period ("a.log"), or the
410/// rotation period (in our case, one day) is less than the time period encoded
411/// in the pattern (in case of "a.log.%Y%M" the period is one month).
412///
413/// Also note, that in any cases, when the log pattern includes "%T", or encodes
414/// a time period that coincides the rotation period (in case of "a.log.%Y%M%D"
415/// the period is one day), then a unique name on each rotation is produced with
416/// the (local) time at which file rotation occurred embedded in the filename.
417///
418/// ## Thread Safety {#ball_asyncfileobserver-thread-safety}
419///
420///
421/// All public methods of `ball::AsyncFileObserver` are thread-safe, and can be
422/// called concurrently by multiple threads.
423///
424/// ## Usage {#ball_asyncfileobserver-usage}
425///
426///
427/// This section illustrates intended use of this component.
428///
429/// ### Example 1: Publication Through the Logger Manager {#ball_asyncfileobserver-example-1-publication-through-the-logger-manager}
430///
431///
432/// This example demonstrates using a `ball::AsyncFileObserver` within the
433/// `ball` logging system.
434///
435/// First, we initialize the `ball` logging subsystem with the default
436/// configuration:
437/// @code
438/// ball::LoggerManagerConfiguration configuration;
439/// ball::LoggerManagerScopedGuard guard(configuration);
440///
441/// ball::LoggerManager& manager = ball::LoggerManager::singleton();
442/// @endcode
443/// Note that the application is now prepared to log messages using the `ball`
444/// logging subsystem, but until the application registers an observer, all log
445/// records will be discarded.
446///
447/// Then, we create a shared pointer to a `ball::AsyncFileObserver` object,
448/// `observerPtr`, having default attributes. Note that a default-constructed
449/// async file observer has a maximum (fixed) size of 8192 for its log record
450/// queue and will drop incoming log records when that queue is full. (See
451/// {Log Record Queue} for further information.)
452/// @code
453/// bsl::shared_ptr<ball::AsyncFileObserver> observer =
454/// bsl::make_shared<ball::AsyncFileObserver>();
455/// @endcode
456/// Next, we set the required logging format by calling the `setLogFormat`
457/// method. The statement below outputs timestamps in ISO 8601 format to a log
458/// file and in `bdlt`-style (default) format to `stdout`, where timestamps are
459/// output with millisecond precision in both cases:
460/// @code
461/// observer->setLogFormat("%I %p:%t %s %f:%l %c %m\n",
462/// "%d %p:%t %s %f:%l %c %m\n");
463/// @endcode
464/// Note that both of the above format specifications omit user fields (`%u`) in
465/// the output. Also note that, unlike the default, this format does not emit a
466/// blank line between consecutive log messages.
467///
468/// Next, we start the publication thread by invoking `startPublicationThread`:
469/// @code
470/// observer->startPublicationThread();
471/// @endcode
472/// Then, we register the async file observer with the logger manager. Upon
473/// successful registration, the observer will start to receive log records via
474/// the `publish` method:
475/// @code
476/// int rc = manager.registerObserver(observer, "asyncObserver");
477/// assert(0 == rc);
478/// @endcode
479/// Next, we set the log category and log a few records with different logging
480/// severity. By default, only the records with `e_WARN`, `e_ERROR`, or
481/// `e_FATAL` severity will be logged to `stdout`. Note that logging to a file
482/// is not enabled by default:
483/// @code
484/// BALL_LOG_SET_CATEGORY("ball::AsyncFileObserverTest");
485///
486/// BALL_LOG_INFO << "Will not be published on 'stdout'.";
487/// BALL_LOG_WARN << "This warning *will* be published on 'stdout'.";
488/// @endcode
489/// Then, we change the default severity for logging to `stdout` by calling the
490/// `setStdoutThreshold` method:
491/// @code
492/// observerPtr->setStdoutThreshold(ball::Severity::e_INFO);
493///
494/// BALL_LOG_DEBUG << "This debug message is not published on 'stdout'.";
495/// BALL_LOG_INFO << "This info will be published on 'stdout'.";
496/// BALL_LOG_WARN << "This warning will be published on 'stdout'.";
497/// @endcode
498/// Next, we disable logging to `stdout` and enable logging to a file:
499/// @code
500/// observer->setStdoutThreshold(ball::Severity::e_OFF);
501///
502/// // Create and log records to a file named "/var/log/task/task.log".
503/// observer->enableFileLogging("/var/log/task/task.log");
504/// @endcode
505/// Note that logs are now asynchronously written to the file.
506///
507/// Then, we specify rules for log file rotation based on the size and time
508/// interval:
509/// @code
510/// // Rotate the file when its size becomes greater than or equal to 32
511/// // megabytes.
512/// observer->rotateOnSize(1024 * 32);
513///
514/// // Rotate the file every 24 hours.
515/// observer->rotateOnTimeInterval(bdlt::DatetimeInterval(1));
516/// @endcode
517/// Note that in this configuration the user may end up with multiple log files
518/// for a specific day (because of the rotation-on-size rule).
519///
520/// Next, we demonstrate how to correctly shut down the async file observer. We
521/// first stop the publication thread by explicitly calling the
522/// `stopPublicationThread` method. This method blocks until all the log
523/// records that were on the record queue on entry to `stopPublicationThread`
524/// have been published:
525/// @code
526/// observer->stopPublicationThread();
527/// @endcode
528/// Then, we disable the log rotation rules established earlier and also
529/// completely disable logging to a file:
530/// @code
531/// observer->disableSizeRotation();
532///
533/// observer->disableTimeIntervalRotation();
534///
535/// observer->disableFileLogging();
536/// @endcode
537/// Note that stopping the publication thread and disabling various features of
538/// the async file observer is not strictly necessary before object destruction.
539/// In particular, if a publication thread is still running when the destructor
540/// is invoked, all records on the record queue upon entry are published and
541/// then the publication thread is automatically stopped before destroying the
542/// async file observer. In any case, all resources managed by the async file
543/// observer will be released when the object is destroyed.
544///
545/// Finally, we can deregister our async file observer from the `ball` logging
546/// subsystem entirely (and destroy the observer later):
547/// @code
548/// rc = manager.deregisterObserver("asyncObserver");
549/// assert(0 == rc);
550/// @endcode
551/// @}
552/** @} */
553/** @} */
554
555/** @addtogroup bal
556 * @{
557 */
558/** @addtogroup ball
559 * @{
560 */
561/** @addtogroup ball_asyncfileobserver
562 * @{
563 */
564
565#include <balscm_version.h>
566
567#include <ball_context.h>
568#include <ball_fileobserver.h>
569#include <ball_fileobserver2.h>
570#include <ball_observer.h>
571#include <ball_record.h>
573#include <ball_severity.h>
574
575#include <bdlcc_boundedqueue.h>
576
578
579#include <bslma_allocator.h>
580
582
583#include <bslmt_threadutil.h>
584
585#include <bsls_atomic.h>
586#include <bsls_keyword.h>
587#include <bsls_libraryfeatures.h>
588
589#include <bsl_functional.h>
590#include <bsl_memory.h>
591#include <bsl_string.h>
592
593#include <string> // 'std::string', 'std::pmr::string'
594
595
596namespace ball {
597
598 // ===============================
599 // struct AsyncFileObserver_Record
600 // ===============================
601
602/// PRIVATE STRUCT. For use by the `ball::AsyncFileObserver` implementation
603/// only. This `struct` holds a log record and its associated context.
605
606 // PUBLIC DATA
608 Context d_context; // context of log record
609};
610
611 // =======================
612 // class AsyncFileObserver
613 // =======================
614
615/// This class implements the `Observer` protocol. The `publish` method of
616/// this class outputs log records asynchronously to `stdout` and optionally
617/// to a user-specified file. This class is thread-safe; different threads
618/// can operate on an object concurrently. This class is exception-neutral
619/// with no guarantee of rollback. In no event is memory leaked.
620///
621/// See @ref ball_asyncfileobserver
623
624 // PRIVATE TYPES
625
626 /// State of the publication thread, as captured by `d_threadState`.
627 enum ThreadState {
628
629 e_RUNNING, // the publication thread is running
630
631 e_NOT_RUNNING // the publication thread is not running
632 };
633
634 // DATA
635 FileObserver d_fileObserver; // forward most public
636 // method calls to this
637 // (non-async) file
638 // observer member
639
640 bslmt::ThreadUtil::Handle d_threadHandle; // handle of asynchronous
641 // publication thread
642
644 d_recordQueue; // fixed-size queue of
645 // records processed by
646 // the publication thread
647
648 bsls::AtomicInt d_threadState; // the publication thread
649 // state, one of the
650 // values of `ThreadState`
651
652 Severity::Level d_dropRecordsOnFullQueueThreshold;
653 // records with severity
654 // below this threshold
655 // are dropped when the
656 // queue is full; default
657 // is `Severity::e_OFF`
658
659 bsls::AtomicInt d_dropCount; // number of dropped
660 // records; reset to 0
661 // each time drop count is
662 // published
663
664 bsl::function<void()> d_publishThreadEntryPoint;
665 // publication thread
666 // entry point functor
667
668 mutable bslmt::Mutex d_mutex; // serialize operations
669
670 bslma::Allocator *d_allocator_p; // memory allocator (held,
671 // not owned)
672
673 private:
674 // NOT IMPLEMENTED
676 AsyncFileObserver& operator=(const AsyncFileObserver&);
677
678 // PRIVATE MANIPULATORS
679
680 /// Initialize members of this object that do not vary between
681 /// constructor overloads. Note that this method should be removed when
682 /// C++11 constructor chaining is available on all supported platforms.
683 void construct();
684
685 /// Publish records from the record queue, to the log file and `stdout`,
686 /// until signaled to stop. The behavior is undefined if this method is
687 /// invoked concurrently from multiple threads, i.e., it is *not*
688 /// thread-safe. Note that this function is the entry point for the
689 /// publication thread.
690 void publishThreadEntryPoint();
691
692 public:
693 // TYPES
694
695 /// `OnFileRotationCallback` is an alias for a user-supplied callback
696 /// function that is invoked after the file observer attempts to rotate
697 /// its log file. The callback takes two arguments: (1) an integer
698 /// status value where 0 indicates a new log file was successfully
699 /// created and a non-zero value indicates an error occurred during
700 /// rotation, and (2) a string that provides the name of the rotated log
701 /// file if the rotation was successful. E.g.:
702 /// @code
703 /// void onLogFileRotation(int rotationStatus,
704 /// const bsl::string& rotatedLogFileName);
705 /// @endcode
707
708 // TRAITS
711
712 // CREATORS
713
714 explicit AsyncFileObserver(bslma::Allocator *basicAllocator = 0);
715 /// Create an async file observer that asynchronously publishes log
716 /// records to `stdout` if their severity is at least as severe as the
717 /// optionally specified `stdoutThreshold` level, and has file logging
718 /// initially disabled. If `stdoutThreshold` is not specified, log
719 /// records are published to `stdout` if their severity is at least as
720 /// severe as `Severity::e_WARN`. Optionally specify a `basicAllocator`
721 /// used to supply memory. If `basicAllocator` is 0, the currently
722 /// installed default allocator is used. Records received by the
723 /// `publish` method are appended to a queue having a maximum (fixed)
724 /// length of 8192, and published later by an independent publication
725 /// thread. All records received while the queue is full are discarded.
726 /// (See {Log Record Queue} for further information.) Note that
727 /// `isPublishInLocalTimeEnabled` returns `false` following construction
728 /// indicating that the timestamp attribute of published records will be
729 /// written in UTC time (see `enablePublishInLocalTime`). Also note
730 /// that independent default record formats are in effect for `stdout`
731 /// and file logging (see `setLogFormat`).
733 bslma::Allocator *basicAllocator = 0);
734
735 /// Create an async file observer that asynchronously publishes log
736 /// records to `stdout` if their severity is at least as severe as the
737 /// specified `stdoutThreshold` level, and has file logging initially
738 /// disabled. The timestamp attribute of published records is written
739 /// in local time if the specified `publishInLocalTime` flag is `true`,
740 /// and in UTC time otherwise. Optionally specify a `basicAllocator`
741 /// used to supply memory. If `basicAllocator` is 0, the currently
742 /// installed default allocator is used. Records received by the
743 /// `publish` method are appended to a queue having a maximum (fixed)
744 /// length of 8192, and published later by an independent publication
745 /// thread. All records received while the queue is full are discarded.
746 /// (See {Log Record Queue} for further information.) Note that
747 /// independent default record formats are in effect for `stdout` and
748 /// file logging (see `setLogFormat`).
750 bool publishInLocalTime,
751 bslma::Allocator *basicAllocator = 0);
752
754 bool publishInLocalTime,
755 int maxRecordQueueSize,
756 bslma::Allocator *basicAllocator = 0);
757 /// Create an async file observer that asynchronously publishes log
758 /// records to `stdout` if their severity is at least as severe as the
759 /// specified `stdoutThreshold` level, and has file logging initially
760 /// disabled. The timestamp attribute of published records is written
761 /// in local time if the specified `publishInLocalTime` flag is `true`,
762 /// and in UTC time otherwise. Records received by the `publish` method
763 /// are appended to a queue having the specified (fixed)
764 /// `maxRecordQueueSize`, and published later by an independent
765 /// publication thread. Optionally specify a
766 /// `dropRecordsOnFullQueueThreshold` indicating the severity threshold
767 /// below which records received when the queue is full will be
768 /// discarded; records received whose severity is at least as severe as
769 /// this threshold will block the calling thread if the queue is full,
770 /// until space is available. If `dropRecordsOnFullQueueThreshold` is
771 /// not specified, all records received while the queue is full are
772 /// discarded. (See {Log Record Queue} for further information.)
773 /// Optionally specify a `basicAllocator` used to supply memory. If
774 /// `basicAllocator` is 0, the currently installed default allocator is
775 /// used. Note that independent default record formats are in effect
776 /// for `stdout` and file logging (see `setLogFormat`).
778 bool publishInLocalTime,
779 int maxRecordQueueSize,
780 Severity::Level dropRecordsOnFullQueueThreshold,
781 bslma::Allocator *basicAllocator = 0);
782
783 /// Publish all records that were on the record queue upon entry if a
784 /// publication thread is running, stop the publication thread (if any),
785 /// close the log file if file logging is enabled, and destroy this
786 /// async file observer.
788
789 // MANIPULATORS
790
791 /// Disable file logging for this async file observer. This method has
792 /// no effect if file logging is not enabled. Calling this method will
793 /// prevent the logging to a file of any unpublished records held by
794 /// this observer. Note that records subsequently received through the
795 /// `publish` method as well as those that are currently on the queue
796 /// may still be logged to `stdout` after calling this method.
797 void disableFileLogging();
798
799 /// Disable publishing of the timestamp attribute of records in local
800 /// time by this async file observer; henceforth, timestamps will be in
801 /// UTC time. This method has no effect if publishing in local time is
802 /// not enabled. Note that this method also affects log filenames (see
803 /// {Log Filename Patterns}). Also note that this method affects
804 /// records subsequently received through the `publish` method as well
805 /// as those that are currently on the queue.
807
808 /// Disable log file rotation based on log file size for this async file
809 /// observer. This method has no effect if rotation-on-size is not
810 /// enabled.
811 void disableSizeRotation();
812
813 /// Disable this async file observer from using the long output format
814 /// when logging to `stdout`. Henceforth, this async file observer will
815 /// use the default short output format ("\n%s %f:%l %c %m %u\n") when
816 /// logging to `stdout`. This method has no effect if the long output
817 /// format for `stdout` logging is not enabled. Note that this method
818 /// omits the "%d %p:%t " prefix from the default long output format.
819 /// Also note that this method affects records subsequently received
820 /// through the `publish` method as well as those that are currently on
821 /// the queue.
823
824 /// Disable log file rotation based on a periodic time interval for this
825 /// async file observer. This method has no effect if
826 /// rotation-on-time-interval is not enabled.
828
829 /// Enable logging of all records published to this async file observer
830 /// to a file whose name is derived from the specified
831 /// `logFilenamePattern`. Return 0 on success, a positive value if file
832 /// logging is already enabled (with no effect), and a negative value
833 /// otherwise. The basename of `logFilenamePattern` may contain
834 /// `%`-escape sequences that are interpreted as follows:
835 /// @code
836 /// %Y - current year (4 digits with leading zeros)
837 /// %M - current month (2 digits with leading zeros)
838 /// %D - current day (2 digits with leading zeros)
839 /// %h - current hour (2 digits with leading zeros)
840 /// %m - current minute (2 digits with leading zeros)
841 /// %s - current second (2 digits with leading zeros)
842 /// %T - current datetime, equivalent to "%Y%M%D_%h%m%s"
843 /// %p - process ID
844 /// @endcode
845 /// Each time a log file is opened by this async file observer (upon a
846 /// successful call to this method and following each log file
847 /// rotation), the name of the new log file is derived from
848 /// `logFilenamePattern` by interpreting the above recognized `%`-escape
849 /// sequences. If `isPublishInLocalTimeEnabled` returns `true`, the
850 /// `%`-escape sequences related to time will be substituted with local
851 /// time values, and UTC time values otherwise. Note that, if a
852 /// publication thread is running, it will now publish queued records to
853 /// the log file where it previously was only publishing queued records
854 /// to `stdout`.
855 int enableFileLogging(const char *logFilenamePattern);
856
857 /// Enable this async file observer to use the long output format when
858 /// logging to `stdout`. Henceforth, this async file observer will use
859 /// the output format for `stdout` logging that was set by the most
860 /// recent call to `setLogFormat`, or the default long output format
861 /// ("\n%d %p:%t %s %f:%l %c %m %u\n") if `setLogFormat` has not yet
862 /// been called. This method has no effect if the long output format
863 /// for `stdout` logging is already enabled. Note that this method
864 /// affects records subsequently received through the `publish` method
865 /// as well as those that are currently on the queue.
867
868 /// Enable publishing of the timestamp attribute of records in local
869 /// time by this async file observer. This method has no effect if
870 /// publishing in local time is already enabled. Note that this method
871 /// also affects log filenames (see {Log Filename Patterns}). Also note
872 /// that this method affects records subsequently received through the
873 /// `publish` method as well as those that are currently on the queue.
875
876 /// Forcefully perform a log file rotation by this async file observer.
877 /// Close the current log file, rename the log file if necessary, and
878 /// open a new log file. This method has no effect if file logging is
879 /// not enabled. See {Rotated File Naming} for details on filenames of
880 /// rotated log files.
881 void forceRotation();
882
883 using Observer::publish; // Avoid hiding base class.
884
885 /// Process the record referenced by the specified `record` shared
886 /// pointer having the specified publishing `context` by writing the
887 /// record and `context` to the current log file if file logging is
888 /// enabled for this async file observer, and to `stdout` if the
889 /// severity of `record` is at least as severe as the value returned by
890 /// `stdoutThreshold`. `record` and `context` are appended to the
891 /// record queue and published (asynchronously) later by the publication
892 /// thread. If the queue is full, `record` and `context` are discarded
893 /// unless the constructor taking `dropRecordsOnFullQueueThreshold` was
894 /// used; if `dropRecordsOnFullQueueThreshold` was supplied with a
895 /// `Severity::Level` at construction, `record` and `context` are
896 /// discarded only if the severity of `record` is below that threshold,
897 /// otherwise, this method will block waiting until space is available
898 /// on the queue. See {Log Record Queue} for further information.
899 void publish(const bsl::shared_ptr<const Record>& record,
900 const Context& context)
902
903 /// Discard any shared references to `Record` objects that were supplied
904 /// to the `publish` method, and are held by this observer. Note that
905 /// this operation should be called if resources underlying the
906 /// previously provided shared pointers must be released. Also note
907 /// that all currently queued records are discarded.
909
910 /// Set this async file observer to perform log file rotation when the
911 /// size of the file exceeds the specified `size` (in kilobytes). This
912 /// rule replaces any rotation-on-size rule currently in effect. The
913 /// behavior is undefined unless `size > 0`.
914 void rotateOnSize(int size);
915
916 void rotateOnTimeInterval(const bdlt::DatetimeInterval& interval);
917 /// Set this file observer to perform a periodic log file rotation at
918 /// multiples of the specified `interval`. Optionally specify a
919 /// `startTime` indicating the datetime to use as the starting point for
920 /// computing the periodic rotation schedule. If
921 /// `isPublishInLocalTimeEnabled` is `true`, the `startTime` is
922 /// interpreted as local time, and as a UTC time otherwise. If
923 /// `startTime` is not specified, the current time is used. This rule
924 /// replaces any rotation-on-time-interval rule currently in effect.
925 /// The behavior is undefined unless `0 < interval.totalMilliseconds()`.
926 /// Note that `startTime` may be a fixed time in the past; e.g., a
927 /// reference time of `bdlt::Datetime(1, 1, 1)` and an interval of 24
928 /// hours would configure a periodic rotation at midnight each day.
929 void rotateOnTimeInterval(const bdlt::DatetimeInterval& interval,
930 const bdlt::Datetime& startTime);
931
932 /// Set the format specifications for log records written to the log
933 /// file and to `stdout` to the specified `logFileFormat` and
934 /// `stdoutFormat`, respectively. If the default short output format is
935 /// currently in effect for logging to `stdout`, this method has the
936 /// effect of calling `enableStdoutLoggingPrefix` (see that method and
937 /// `disableStdoutLoggingPrefix`). See {Log Record Formatting} for
938 /// details on the syntax of format specifications. Note that default
939 /// formats are in effect following construction until this method is
940 /// called ("\n%d %p:%t %s %f:%l %c %m %u\n" for both file and `stdout`
941 /// logging). Also note that the observer emits newline characters at
942 /// the beginning and at the end of a log record by default, so the user
943 /// needs to add them explicitly to the format string to preserve this
944 /// behavior. Also note that this method affects records subsequently
945 /// received through the `publish` method as well as those that are
946 /// currently on the queue.
947 void setLogFormat(const char *logFileFormat, const char *stdoutFormat);
948
949 /// Set the specified `onRotationCallback` to be invoked after each time
950 /// this async file observer attempts to perform a log file rotation.
951 /// The behavior is undefined if the supplied function calls either
952 /// `setOnFileRotationCallback`, `forceRotation`, or `publish` on this
953 /// async file observer (i.e., the supplied callback should *not*
954 /// attempt to write to the `ball` log).
956 const OnFileRotationCallback& onRotationCallback);
957
958 /// Set the minimum severity of records logged to `stdout` by this async
959 /// file observer to the specified `stdoutThreshold` level. Note that
960 /// if the value of `stdoutThreshold` is `Severity::e_OFF`, logging to
961 /// `stdout` is disabled. Also note that this method affects records
962 /// subsequently received through the `publish` method as well as those
963 /// that are currently on the queue.
965
966 /// Stop the publication thread without waiting for log records
967 /// currently on the record queue to be published. Return 0 on success,
968 /// and a non-zero value if there is an error joining the publication
969 /// thread. Note that log records received by the `publish` method will
970 /// continue to be added to the queue after the publication thread is
971 /// shut down.
973
974 /// Start a publication thread to asynchronously publish log records
975 /// from the record queue. If a publication thread is already active,
976 /// this operation has no effect. Return 0 on success, and a non-zero
977 /// value if there is an error creating the publication thread. Note
978 /// that log records received by the `publish` method may have
979 /// accumulated on the queue before the publication thread is started.
981
982 /// Block until all records that were on the record queue upon entry
983 /// have been published, then stop the publication thread. If there is
984 /// no publication thread this operation has no effect. Return 0 on
985 /// success, and a non-zero value if there is an error joining the
986 /// publication thread. Note that log records received by the `publish`
987 /// method will continue to be added to the queue after the publication
988 /// thread is stopped.
990
991 /// Suppress generating a unique log file name upon rotation if the
992 /// specified `suppress` is `true`, and generate a unique filename
993 /// otherwise. See {Rotated File Naming} for details.
994 void suppressUniqueFileNameOnRotation(bool suppress);
995
996 // ACCESSORS
997
998 /// Load the format specification for log records written by this async
999 /// file observer to the log file into the specified `*logFileFormat`
1000 /// address and the format specification for log records written to
1001 /// `stdout` into the specified `*stdoutFormat` address. See {Log
1002 /// Record Formatting} for details on the syntax of format
1003 /// specifications.
1004 void getLogFormat(const char **logFileFormat,
1005 const char **stdoutFormat) const;
1006
1007 /// Return `true` if file logging is enabled for this async file
1008 /// observer, and `false` otherwise. Load the optionally specified
1009 /// `result` with the name of the current log file if file logging is
1010 /// enabled, and leave `result` unmodified otherwise. Note that records
1011 /// received through the `publish` method of this async file observer
1012 /// may still be logged to `stdout` when this method returns `false`.
1013 bool isFileLoggingEnabled() const;
1014 bool isFileLoggingEnabled(bsl::string *result) const;
1015 bool isFileLoggingEnabled(std::string *result) const;
1016
1017#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1018 /// Return `true` if file logging is enabled for this async file
1019 /// observer, and `false` otherwise. Load the specified `result` with
1020 /// the name of the current log file if file logging is enabled, and
1021 /// leave `result` unmodified otherwise. Note that records received
1022 /// through the `publish` method of this async file observer may still
1023 /// be logged to `stdout` when this method returns `false`.
1024 bool isFileLoggingEnabled(std::pmr::string *result) const;
1025#endif // BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1026
1027 /// Return `true` if a publication thread is running, and `false`
1028 /// otherwise. Note that records received by the `publish` method will
1029 /// still be added to the record queue even if there is no publication
1030 /// thread running.
1031 bool isPublicationThreadRunning() const;
1032
1033 /// Return `true` if this async file observer writes the timestamp
1034 /// attribute of records that it publishes in local time, and `false`
1035 /// otherwise (in which case timestamps are written in UTC time). Note
1036 /// that the value returned by this method also affects log filenames
1037 /// (see {Log Filename Patterns}).
1038 bool isPublishInLocalTimeEnabled() const;
1039
1040 /// Return `true` if this async file observer uses the long output
1041 /// format when writing to `stdout`, and `false` otherwise (in which
1042 /// case the default short output format is used). See
1043 /// `enableStdoutLoggingPrefix` and `disableStdoutLoggingPrefix`.
1044 bool isStdoutLoggingPrefixEnabled() const;
1045
1046 /// Return `true` if the log filename uniqueness check on rotation is
1047 /// suppressed, and false otherwise.
1049
1050 /// Return `true` if the logging of user-defined fields is enabled for
1051 /// this async file observer, and `false` otherwise.
1052 ///
1053 /// @deprecated Do not use.
1054 bool isUserFieldsLoggingEnabled() const;
1055
1056#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1057 /// Return the difference between the local time and UTC time in effect
1058 /// when this async file observer was constructed. Note that this value
1059 /// remains unchanged during the lifetime of this object and therefore
1060 /// may become incorrect when the difference between the local time and
1061 /// UTC time changes (e.g., when transitioning into or out of daylight
1062 /// savings time).
1063 ///
1064 /// @deprecated Use @ref bdlt::LocalTimeOffset instead.
1066#endif // BDE_OMIT_INTERNAL_DEPRECATED
1067
1068 /// Return the number of log records currently on the record queue of
1069 /// this async file observer.
1070 bsl::size_t recordQueueLength() const;
1071
1072 /// Return the log file lifetime that will trigger a file rotation by
1073 /// this async file observer if rotation-on-lifetime is in effect, and a
1074 /// 0 time interval otherwise.
1076
1077 /// Return the size (in kilobytes) of the log file that will trigger a
1078 /// file rotation by this async file observer if rotation-on-size is in
1079 /// effect, and 0 otherwise.
1080 int rotationSize() const;
1081
1082 /// Return the minimum severity of records that will be logged to
1083 /// `stdout` by this async file observer. Note that records with a
1084 /// threshold less severe than `stdoutThreshold()` may still be output
1085 /// to the log file if file logging is enabled.
1087};
1088
1089// ============================================================================
1090// INLINE DEFINITIONS
1091// ============================================================================
1092
1093 // -----------------------
1094 // class AsyncFileObserver
1095 // -----------------------
1096
1097// MANIPULATORS
1098inline
1100{
1101 d_fileObserver.disableFileLogging();
1102}
1103
1104inline
1109
1110inline
1112{
1113 d_fileObserver.disableSizeRotation();
1114}
1115
1116inline
1121
1122inline
1127
1128inline
1129int AsyncFileObserver::enableFileLogging(const char *logFilenamePattern)
1130{
1131 return d_fileObserver.enableFileLogging(logFilenamePattern);
1132}
1133
1134inline
1139
1140inline
1145
1146inline
1148{
1149 d_fileObserver.forceRotation();
1150}
1151
1152inline
1154{
1155 d_fileObserver.rotateOnSize(size);
1156}
1157
1158inline
1160 const bdlt::DatetimeInterval& interval)
1161{
1162 d_fileObserver.rotateOnTimeInterval(interval);
1163}
1164
1165inline
1167 const bdlt::DatetimeInterval& interval,
1168 const bdlt::Datetime& startTime)
1169{
1170 d_fileObserver.rotateOnTimeInterval(interval, startTime);
1171}
1172
1173inline
1174void AsyncFileObserver::setLogFormat(const char *logFileFormat,
1175 const char *stdoutFormat)
1176{
1177 d_fileObserver.setLogFormat(logFileFormat, stdoutFormat);
1178}
1179
1180inline
1182 const OnFileRotationCallback& onRotationCallback)
1183{
1184 d_fileObserver.setOnFileRotationCallback(onRotationCallback);
1185}
1186
1187inline
1189{
1190 d_fileObserver.FileObserver::setStdoutThreshold(stdoutThreshold);
1191}
1192
1193inline
1195{
1196 d_fileObserver.suppressUniqueFileNameOnRotation(suppress);
1197}
1198
1199// ACCESSORS
1200inline
1201void AsyncFileObserver::getLogFormat(const char **logFileFormat,
1202 const char **stdoutFormat) const
1203{
1204 d_fileObserver.getLogFormat(logFileFormat, stdoutFormat);
1205}
1206
1207inline
1209{
1210 return d_fileObserver.isFileLoggingEnabled();
1211}
1212
1213inline
1215{
1216 return d_fileObserver.isFileLoggingEnabled(result);
1217}
1218
1219inline
1220bool AsyncFileObserver::isFileLoggingEnabled(std::string *result) const
1221{
1222 return d_fileObserver.isFileLoggingEnabled(result);
1223}
1224
1225#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1226inline
1227bool AsyncFileObserver::isFileLoggingEnabled(std::pmr::string *result) const
1228{
1229 return d_fileObserver.isFileLoggingEnabled(result);
1230}
1231#endif // BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1232
1233inline
1235{
1236 return bslmt::ThreadUtil::invalidHandle() != d_threadHandle;
1237}
1238
1239inline
1241{
1242 return d_fileObserver.isPublishInLocalTimeEnabled();
1243}
1244
1245inline
1247{
1248 return d_fileObserver.isStdoutLoggingPrefixEnabled();
1249}
1250
1251inline
1256
1257inline
1259{
1260 return d_fileObserver.isUserFieldsLoggingEnabled();
1261}
1262
1263#ifndef BDE_OMIT_INTERNAL_DEPRECATED
1264inline
1266{
1267 return d_fileObserver.localTimeOffset();
1268}
1269#endif // BDE_OMIT_INTERNAL_DEPRECATED
1270
1271inline
1273{
1274 return d_recordQueue.numElements();
1275}
1276
1277inline
1279{
1280 return d_fileObserver.rotationLifetime();
1281}
1282
1283inline
1285{
1286 return d_fileObserver.rotationSize();
1287}
1288
1289inline
1291{
1292 return d_fileObserver.stdoutThreshold();
1293}
1294
1295} // close package namespace
1296
1297
1298#endif
1299
1300// ----------------------------------------------------------------------------
1301// Copyright 2015 Bloomberg Finance L.P.
1302//
1303// Licensed under the Apache License, Version 2.0 (the "License");
1304// you may not use this file except in compliance with the License.
1305// You may obtain a copy of the License at
1306//
1307// http://www.apache.org/licenses/LICENSE-2.0
1308//
1309// Unless required by applicable law or agreed to in writing, software
1310// distributed under the License is distributed on an "AS IS" BASIS,
1311// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1312// See the License for the specific language governing permissions and
1313// limitations under the License.
1314// ----------------------------- END-OF-FILE ----------------------------------
1315
1316/** @} */
1317/** @} */
1318/** @} */
Definition ball_asyncfileobserver.h:622
void suppressUniqueFileNameOnRotation(bool suppress)
Definition ball_asyncfileobserver.h:1194
bdlt::DatetimeInterval rotationLifetime() const
Definition ball_asyncfileobserver.h:1278
void releaseRecords() BSLS_KEYWORD_OVERRIDE
AsyncFileObserver(Severity::Level stdoutThreshold, bslma::Allocator *basicAllocator=0)
~AsyncFileObserver() BSLS_KEYWORD_OVERRIDE
void setOnFileRotationCallback(const OnFileRotationCallback &onRotationCallback)
Definition ball_asyncfileobserver.h:1181
bdlt::DatetimeInterval localTimeOffset() const
Definition ball_asyncfileobserver.h:1265
void enablePublishInLocalTime()
Definition ball_asyncfileobserver.h:1135
void setLogFormat(const char *logFileFormat, const char *stdoutFormat)
Definition ball_asyncfileobserver.h:1174
bool isPublicationThreadRunning() const
Definition ball_asyncfileobserver.h:1234
void disableTimeIntervalRotation()
Definition ball_asyncfileobserver.h:1123
void enableStdoutLoggingPrefix()
Definition ball_asyncfileobserver.h:1141
void forceRotation()
Definition ball_asyncfileobserver.h:1147
void disablePublishInLocalTime()
Definition ball_asyncfileobserver.h:1105
BSLMF_NESTED_TRAIT_DECLARATION(AsyncFileObserver, bslma::UsesBslmaAllocator)
Severity::Level stdoutThreshold() const
Definition ball_asyncfileobserver.h:1290
void disableStdoutLoggingPrefix()
Definition ball_asyncfileobserver.h:1117
bool isFileLoggingEnabled() const
Definition ball_asyncfileobserver.h:1208
int enableFileLogging(const char *logFilenamePattern)
Definition ball_asyncfileobserver.h:1129
void publish(const bsl::shared_ptr< const Record > &record, const Context &context) BSLS_KEYWORD_OVERRIDE
AsyncFileObserver(bslma::Allocator *basicAllocator=0)
bool isSuppressUniqueFileNameOnRotation() const
Definition ball_asyncfileobserver.h:1252
bool isPublishInLocalTimeEnabled() const
Definition ball_asyncfileobserver.h:1240
bsl::size_t recordQueueLength() const
Definition ball_asyncfileobserver.h:1272
bool isUserFieldsLoggingEnabled() const
Definition ball_asyncfileobserver.h:1258
FileObserver::OnFileRotationCallback OnFileRotationCallback
Definition ball_asyncfileobserver.h:706
int rotationSize() const
Definition ball_asyncfileobserver.h:1284
void rotateOnTimeInterval(const bdlt::DatetimeInterval &interval)
Definition ball_asyncfileobserver.h:1159
AsyncFileObserver(Severity::Level stdoutThreshold, bool publishInLocalTime, int maxRecordQueueSize, Severity::Level dropRecordsOnFullQueueThreshold, bslma::Allocator *basicAllocator=0)
AsyncFileObserver(Severity::Level stdoutThreshold, bool publishInLocalTime, bslma::Allocator *basicAllocator=0)
void disableSizeRotation()
Definition ball_asyncfileobserver.h:1111
void setStdoutThreshold(Severity::Level stdoutThreshold)
Definition ball_asyncfileobserver.h:1188
void rotateOnSize(int size)
Definition ball_asyncfileobserver.h:1153
AsyncFileObserver(Severity::Level stdoutThreshold, bool publishInLocalTime, int maxRecordQueueSize, bslma::Allocator *basicAllocator=0)
bool isStdoutLoggingPrefixEnabled() const
Definition ball_asyncfileobserver.h:1246
void disableFileLogging()
Definition ball_asyncfileobserver.h:1099
void getLogFormat(const char **logFileFormat, const char **stdoutFormat) const
Definition ball_asyncfileobserver.h:1201
Definition ball_context.h:295
Definition ball_fileobserver.h:515
int enableFileLogging(const char *logFilenamePattern)
Definition ball_fileobserver.h:944
void getLogFormat(const char **logFileFormat, const char **stdoutFormat) const
bool isSuppressUniqueFileNameOnRotation() const
Definition ball_fileobserver.h:1042
bdlt::DatetimeInterval rotationLifetime() const
Definition ball_fileobserver.h:1054
bool isFileLoggingEnabled() const
Definition ball_fileobserver.h:1016
void disablePublishInLocalTime()
bool isStdoutLoggingPrefixEnabled() const
void disableSizeRotation()
Definition ball_fileobserver.h:932
void enablePublishInLocalTime()
void disableStdoutLoggingPrefix()
void rotateOnSize(int size)
Definition ball_fileobserver.h:982
bool isUserFieldsLoggingEnabled() const
void setOnFileRotationCallback(const OnFileRotationCallback &onRotationCallback)
Definition ball_fileobserver.h:1002
bdlt::DatetimeInterval localTimeOffset() const
Definition ball_fileobserver.h:1048
bool isPublishInLocalTimeEnabled() const
void rotateOnTimeInterval(const bdlt::DatetimeInterval &interval)
Definition ball_fileobserver.h:988
void disableTimeIntervalRotation()
Definition ball_fileobserver.h:938
void suppressUniqueFileNameOnRotation(bool suppress)
Definition ball_fileobserver.h:1009
void setLogFormat(const char *logFileFormat, const char *stdoutFormat)
void forceRotation()
Definition ball_fileobserver.h:958
void disableFileLogging()
Definition ball_fileobserver.h:920
void enableStdoutLoggingPrefix()
int rotationSize() const
Definition ball_fileobserver.h:1060
Severity::Level stdoutThreshold() const
Definition ball_observer.h:235
Definition ball_record.h:178
Definition bdlcc_boundedqueue.h:415
bsl::size_t numElements() const
Definition bdlcc_boundedqueue.h:1416
Definition bdlt_datetimeinterval.h:201
Definition bdlt_datetime.h:331
Definition bslstl_string.h:1281
Forward declaration.
Definition bslstl_function.h:934
Definition bslstl_sharedptr.h:1830
Definition bslma_allocator.h:457
Definition bslmt_mutex.h:315
Definition bsls_atomic.h:743
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:653
Definition ball_administration.h:214
Definition bbldc_basicisma30360.h:112
Definition bdlb_printmethods.h:283
Definition bdldfp_decimal.h:5188
Definition ball_asyncfileobserver.h:604
Context d_context
Definition ball_asyncfileobserver.h:608
bsl::shared_ptr< const Record > d_record
Definition ball_asyncfileobserver.h:607
This struct provides a namespace for enumerating severity levels.
Definition ball_severity.h:164
Level
Definition ball_severity.h:167
Definition bslma_usesbslmaallocator.h:343
Imp::Handle Handle
Definition bslmt_threadutil.h:385
static const Handle & invalidHandle()
Definition bslmt_threadutil.h:1057