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