// ball_fileobserver2.h -*-C++-*- #ifndef INCLUDED_BALL_FILEOBSERVER2 #define INCLUDED_BALL_FILEOBSERVER2 #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a thread-safe observer that emits log records to a file. // //@CLASSES: // ball::FileObserver2: observer that outputs log records to a file // //@SEE_ALSO: ball_record, ball_context, ball_observer, // ball_recordstringformatter // //@DESCRIPTION: This component provides a concrete implementation of the // 'ball::Observer' protocol, 'ball::FileObserver2', for publishing log records // to a user-specified file. The following inheritance hierarchy diagram shows // the classes involved and their methods: //.. // ,-------------------. // ( ball::FileObserver2 ) // `-------------------' // | ctor // | disableFileLogging // | disableTimeIntervalRotation // | disableSizeRotation // | disablePublishInLocalTime // | enableFileLogging // | enablePublishInLocalTime // | forceRotation // | rotateOnSize // | rotateOnTimeInterval // | setLogFileFunctor // | setOnFileRotationCallback // | suppressUniqueFileNameOnRotation // | isFileLoggingEnabled // | isPublishInLocalTimeEnabled // | isSuppressUniqueFileNameOnRotation // | rotationLifetime // | rotationSize // V // ,--------------. // ( ball::Observer ) // `--------------' // dtor // publish // releaseRecords //.. // A 'ball::FileObserver2' object processes the log records received through // its 'publish' method by writing them to a user-specified file. Note that // the 'enableFileLogging' method must be called to enable logging since // logging to a file is initially disabled following construction. The format // of published log records is user-configurable (see {Log Record Formatting} // below). In addition, a file observer may be configured to perform automatic // log file rotation (see {Log File Rotation} below). // ///File Observer Configuration Synopsis ///------------------------------------ // 'ball::FileObserver2' offers several manipulators that may be used to // configure various aspects of a file observer object. These are summarized // in the following table along with the accessors that can be used to query // the current state of the configuration. Further details are provided in the // following sections and the function-level documentation. //.. // +-------------+------------------------------------+ // | Aspect | Related Methods | // +=============+====================================+ // | Log Record | setLogFileFunctor | // | Formatting | | // +-------------+------------------------------------+ // | Log Record | enablePublishInLocalTime | // | Timestamps | disablePublishInLocalTime | // | | isPublishInLocalTimeEnabled | // +-------------+------------------------------------+ // | File | enableFileLogging | // | Logging | disableFileLogging | // | | isFileLoggingEnabled | // +-------------+------------------------------------+ // | Log File | rotateOnSize | // | Rotation | rotateOnTimeInterval | // | | disableSizeRotation | // | | disableTimeIntervalRotation | // | | setOnFileRotationCallback | // | | suppressUniqueFileNameOnRotation | // | | rotationSize | // | | rotationLifetime | // | | isSuppressUniqueFileNameOnRotation | // +-------------+------------------------------------+ //.. // In general, a 'ball::FileObserver2' object can be dynamically configured // throughout its lifetime (in particular, before or after being registered // with a logger manager). However, note that for 'ball::FileObserver2', // configuration changes that affect how records are logged (e.g., // 'enablePublishInLocalTime' and 'disablePublishInLocalTime') impact only // those records that are published subsequent to making the configuration // change. // ///Log Record Formatting ///--------------------- // By default, the output format of published log records is: //.. // DATE_TIME PID:THREAD-ID SEVERITY FILE:LINE CATEGORY MESSAGE USER-FIELDS //.. // where 'DATE' and 'TIME' are of the form 'DDMonYYYY' and 'HH:MM:SS.mmm', // respectively ('Mon' being the 3-letter abbreviation for the month). For // example, assuming that no user-defined fields are present, a log record // will have the following appearance when the default format is in effect: //.. // 18MAY2005_18:58:12.076 7959:1 WARN ball_fileobserver2.t.cpp:404 TEST hello! //.. // The default format can be overridden by supplying a suitable formatting // functor to 'setLogFileFunctor'. For example, an instance of // 'ball::RecordStringFormatter' conveniently provides such a functor: //.. // fileObserver.setLogFileFunctor( // ball::RecordStringFormatter("\n%I %p:%t %s %f:%l %c %m %u\n")); //.. // The above statement will cause subsequent records to be logged in a format // that is almost identical to the default format except that the timestamp // attribute will be written in ISO 8601 format. See // {'ball_recordstringformatter'} for information on how format specifications // are defined and interpreted. // // Note that the observer emits newline characters at the beginning and at the // end of a log record by default, so the user needs to add them explicitly to // the format string to preserve this behavior. // // Also note that in the sample message above the timestamp has millisecond // precision ('18MAY2005_18:58:12.076'). If microsecond precision is desired // instead, consider using either the '%D' or '%O' format specification // supported by 'ball_recordstringformatter'. // ///Log Record Timestamps ///--------------------- // By default, the timestamp attributes of published records are written in UTC // time. To write timestamps in local time instead, call the // 'enablePublishInLocalTime' method. Note that the local time offset is // calculated using the UTC timestamp of each record. To revert to UTC time, // call the 'disablePublishInLocalTime' method. Whether UTC time or local time // is in effect can be queried via 'isPublishInLocalTimeEnabled'. However, // note that if the user installs a log record formatting functor via // 'setLogFileFunctor' that is not a 'ball::RecordStringFormatter', then the // supplied functor determines how record timestamps are rendered to the log. // ///Local Time Offset Calculations /// - - - - - - - - - - - - - - - // The calculation of the local time offset adds some overhead to the // publication of each log record. If this overhead is an issue, it can be // mitigated by installing a high-performance local-time offset callback for // 'bdlt::CurrentTime' in 'main'. See {'bsls_systemtime'} for the details of // installing such a callback and see {'baltzo_localtimeoffsetutil'} for an // example facility. Note that such callbacks can improve performance for all // users of 'bdlt::CurrentTime', not just the 'ball' logger. // ///Log Filename Patterns ///--------------------- // The 'enableFileLogging' method supports the use of '%'-escape sequences to // specify log filenames. The recognized sequences are as follows: //.. // %Y - current year (4 digits with leading zeros) // %M - current month (2 digits with leading zeros) // %D - current day (2 digits with leading zeros) // %h - current hour (2 digits with leading zeros) // %m - current minute (2 digits with leading zeros) // %s - current second (2 digits with leading zeros) // %T - current datetime, equivalent to "%Y%M%D_%h%m%s" // %p - process ID //.. // The date and time elements of the derived filename are based on the time // when the log file is created. Furthermore, these elements are based on // either UTC time or local time depending on the value returned by // 'isPublishInLocalTimeEnabled'. (See {Log Record Timestamps} for the // similarity with the treatment of record timestamps.) // // For example, a log filename pattern of "task.log.%Y%M%D_%h%m%s" will yield // the filename 'task.log.20110501_123000' if the file is created on // 01-May-2011 at 12:30:00 local time (assuming 'enablePublishInLocalTime' was // called). // ///Log File Rotation ///----------------- // A 'ball::FileObserver2' may be configured to perform automatic rotation of // log files based on simple file rotation conditions (or rules). // ///File Rotation Conditions /// - - - - - - - - - - - - // Rotation rules may be established based on the size of the log file (i.e., a // "rotation-on-size" rule), and a periodic time interval (i.e., a // "rotation-on-time-interval" rule). These rules are independently enabled by // the 'rotateOnSize' and 'rotateOnTimeInterval' methods, respectively. If // both rules are in effect, log file rotation is performed whenever either // rule applies. // ///Rotated File Naming ///- - - - - - - - - - // When a log file is rotated, a new filename is generated using the pattern // supplied to 'enableFileLogging'. If the file having the new name does not // exist, the current log file is closed, and the logging continues to the new // file. // // If the file having the new name already exits, then the behavior of the file // rotation is further controlled by the flag set with // 'suppressUniqueFileNameOnRotation': // //: o 'suppressUniqueFileNameOnRotation(false)' (*default* behavior) //: The current log filename is renamed by appending a timestamp in the form //: ".%Y%M%D_%h%m%s" where the timestamp indicates when the file being //: rotated was last opened (the time of either the last file rotation or the //: last call to 'enableFileLogging', whichever is most recent). As with the //: timestamps of logged records, the timestamps appended to log filenames //: upon rotation will be in UTC time or local time depending on the value //: returned by 'isPublishInLocalTimeEnabled'. //: //: o 'suppressUniqueFileNameOnRotation(true)' //: The logging continues to the *current* log file, effectively suppressing //: log filename rotation. This may happen when the log file pattern does //: not contain %-escape sequences indicating a time period, or the rotation //: interval is less than the time period encoded by %-escape sequences. In //: order to rotate log files in this mode, the log file pattern MUST contain //: %-escape sequences that specify date and (optionally) time. For example, //: the log filename pattern "app_%Y%M%D.log" will produce a single log file //: per calendar day (assuming, the rotation on time is enabled and the //: rotation happens at least once a day). // // The two tables below illustrate the names of old and new log files when a // file rotation occurs. We assume that the log file is rotated on 2011-May-21 // at 12:29:59 local time and that the last rotation occurred at 12:30:00 on // the previous day. We further assume that 'enablePublishInLocalTime' was // called, so that all date and time elements are rendered in local time. // // The first table shows the name change (if any) of the (old) log file being // rotated when the flag controlled by 'suppressUniqueFileNameOnRotation' // is set to 'false': //.. // Disabled: 'suppressUniqueFileNameOnRotation' // // For brevity: // <TS1> = 20210520_123000 // <TS2> = 20210521_122959 (aka next day, about the same time) // // +----------------+-----------------+----------------+---------------------- // | Pattern | Filename Before | Filename After | Rotated Filename // | | Rotation | Rotation | // +----------------+-----------------+----------------+---------------------- // | "a.log" | a.log | a.log | a.log.<TS1> // | "a.log.%T" | a.log.<TS1> | a.log.<TS2> | a.log.<TS1> // | "a.log.%Y%M" | a.log.202105 | a.log.202105 | a.log.202105.<TS1> // | "a.log.%Y%M%D" | a.log.20210520 | a.log.20110521 | a.log.20210520 // +----------------+-----------------+----------------+---------------------- //.. // Note that upon rotation a timestamp was appended to the name of the rotated // file when the log pattern does not contain %-escape sequences indicating a // time period ("a.log"), or the rotation period (in our case, one day) is less // than the time period encoded in the pattern (in case of "a.log.%Y%M" the // period is one month). // // The next table shows the rotated name when the flag controlled by // 'suppressUniqueFileNameOnRotation' is set to 'true', and (possibly new) name // of the (new) log file following rotation: //.. // Enabled: 'suppressUniqueFileNameOnRotation' // // +----------------+-----------------+----------------+---------------------- // | Pattern | Filename Before | Filename After | Rotated Filename // | | Rotation | Rotation | // +----------------+-----------------+----------------+---------------------- // | "a.log" | a.log | a.log | none // | "a.log.%T" | a.log.<TS1> | a.log.<TS2> | a.log.<TS1> // | "a.log.%Y%M" | a.log.202105 | a.log.202105 | none // | "a.log.%Y%M%D" | a.log.20210520 | a.log.20110521 | a.log.20210520 // +----------------+-----------------+----------------+---------------------- //.. // Note that the original filename is reused when the log pattern does not // contain %-escape sequences indicating a time period ("a.log"), or the // rotation period (in our case, one day) is less than the time period encoded // in the pattern (in case of "a.log.%Y%M" the period is one month). // // Also note, that in any cases, when the log pattern includes "%T", or encodes // a time period that coincides the rotation period (in case of "a.log.%Y%M%D" // the period is one day), then a unique name on each rotation is produced with // the (local) time at which file rotation occurred embedded in the filename. // ///Thread Safety ///------------- // All methods of 'ball::FileObserver2' are thread-safe, and can be called // concurrently by multiple threads. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example: Basic Usage /// - - - - - - - - - - // First, we create a 'ball::LoggerManagerConfiguration' object, 'lmConfig', // and set the logging "pass-through" level -- the level at which log records // are published to registered observers -- to 'DEBUG': //.. // int main() // { // ball::LoggerManagerConfiguration lmConfig; // lmConfig.setDefaultThresholdLevelsIfValid(ball::Severity::e_DEBUG); //.. // Next, create a 'ball::LoggerManagerScopedGuard' object whose constructor // takes the configuration object just created. The guard will initialize the // logger manager singleton on creation and destroy the singleton upon // destruction. This guarantees that any resources used by the logger manager // will be properly released when they are not needed: //.. // ball::LoggerManagerScopedGuard guard(lmConfig); // ball::LoggerManager& manager = ball::LoggerManager::singleton(); //.. // Next, we create a 'ball::FileObserver2' object and register it with the // 'ball' logging system; //.. // bsl::shared_ptr<ball::FileObserver2> observer = // bsl::make_shared<ball::FileObserver2>(); //.. // Next, we configure the log file rotation rules: //.. // // Rotate the file when its size becomes greater than or equal to 128 // // megabytes. // observer->rotateOnSize(1024 * 128); // // // Rotate the file every 24 hours. // observer->rotateOnTimeInterval(bdlt::DatetimeInterval(1)); //.. // Note that in this configuration the user may end up with multiple log files // for a specific day (because of the rotation-on-size rule). // // Then, we enable logging to a file: //.. // // Create and log records to a file named "/var/log/task/task.log". // observer->enableFileLogging("/var/log/task/task.log"); //.. // Finally, we register the file observer with the logger manager. Upon // successful registration, the observer will start to receive log records via // the 'publish' method: //.. // int rc = manager.registerObserver(observer, "default"); // assert(0 == rc); // return 0; // } //.. #include <balscm_version.h> #include <ball_observer.h> #include <ball_severity.h> #include <bdls_fdstreambuf.h> #include <bdlt_datetime.h> #include <bdlt_datetimeinterval.h> #include <bslma_allocator.h> #include <bslma_usesbslmaallocator.h> #include <bslmf_nestedtraitdeclaration.h> #include <bslmt_mutex.h> #include <bsls_libraryfeatures.h> #include <bsl_fstream.h> #include <bsl_functional.h> #include <bsl_iosfwd.h> #include <bsl_memory.h> #include <bsl_string.h> #include <string> // 'std::string', 'std::pmr::string' namespace BloombergLP { namespace ball { class Context; class Record; // =================== // class FileObserver2 // =================== class FileObserver2 : public Observer { // This class implements the 'Observer' protocol. The 'publish' method of // this class outputs the log records that it receives to a user-specified // file. This class is thread-safe; different threads can operate on an // object concurrently. This class is exception-neutral with no guarantee // of rollback. In no event is memory leaked. public: // PUBLIC TYPES typedef bsl::function<void(bsl::ostream&, const Record&)> LogRecordFunctor; // 'LogRecordFunctor' is an alias for the type of the functor used for // formatting log records to a stream. typedef bsl::function<void(int, const bsl::string&)> OnFileRotationCallback; // 'OnFileRotationCallback' is an alias for a user-supplied callback // function that is invoked after the file observer attempts to rotate // its log file. The callback takes two arguments: (1) an integer // status value where 0 indicates a new log file was successfully // created and a non-zero value indicates an error occurred during // rotation, and (2) a string that provides the name of the rotated log // file if the rotation was successful. E.g.: //.. // void onLogFileRotation(int rotationStatus, // const bsl::string& rotatedLogFileName); //.. private: // DATA bdls::FdStreamBuf d_logStreamBuf; // stream buffer for // file logging bsl::ostream d_logOutStream; // output stream for // file logging (refers // to 'd_logStreamBuf') bsl::string d_logFilePattern; // log filename pattern bsl::string d_logFileName; // current log filename bdlt::Datetime d_logFileTimestampUtc; // modification time of // the log file when it // was opened (or the // creation time if the // log file did not // already exist) LogRecordFunctor d_logFileFunctor; // formatting functor // used when writing to // log file bool d_publishInLocalTime; // 'true' if timestamps // of records are output // in local time, // otherwise UTC time bool d_suppressUniqueFileName; // 'false' if rotated // log file has a unique // name mutable bslmt::Mutex d_mutex; // serialize operations int d_rotationSize; // maximum log file size // before rotation (in // kilobytes) bdlt::Datetime d_rotationReferenceTime; // reference start time // (time-zone determined // by // d_publishInLocalTime) // for time-based // rotation bdlt::DatetimeInterval d_rotationInterval; // time interval between // two time-based // rotations bdlt::Datetime d_nextRotationTimeUtc; // next scheduled time // for time-based // rotation OnFileRotationCallback d_onRotationCb; // user callback // invoked following // file rotation mutable bslmt::Mutex d_rotationCbMutex; // serialize access to // 'd_onRotationCb'; // required because // callback must be // called with 'd_mutex' // unlocked private: // NOT IMPLEMENTED FileObserver2(const FileObserver2&); FileObserver2& operator=(const FileObserver2&); private: // PRIVATE MANIPULATORS void logRecordDefault(bsl::ostream& stream, const Record& record); // Write the specified log 'record' to the specified output 'stream' // using the default record format of this file observer. int rotateFile(bsl::string *rotatedLogFileName); // Perform a log file rotation by closing the current log file of this // file observer, renaming the closed log file if necessary, and // opening a new log file. Load, into the specified // 'rotatedLogFileName', the name of the rotated log file. Return 0 on // success, a positive value if logging is not enabled, and a negative // value otherwise. The existing log file is renamed if the new log // filename, as determined by the 'logFilenamePattern' of the latest // call to 'enableFileLogging', is the same as the old log filename. int rotateIfNecessary(bsl::string *rotatedLogFileName, const bdlt::Datetime& currentLogTimeUtc); // Perform log file rotation if the specified 'currentLogTimeUtc' is // later than the scheduled rotation time of the current log file, or // if the log file is larger than the allowable size, and if a rotation // is performed, load into the specified 'rotatedLogFileName' the name // of the rotated file. Return 0 if the log file is rotated // successfully, a positive value if a rotation was determined to be // unnecessary, and a negative value otherwise. The rotation schedule // and the allowable file size are set by the 'rotateOnTimeInterval' // and the 'rotateOnSize' methods, respectively. The behavior is // undefined unless the caller acquired the lock for this object. // PRIVATE ACCESSORS template <class t_STRING> bool isFileLoggingEnabledImpl(t_STRING *result) const; // Return 'true' if file logging is enabled for this file observer, and // 'false' otherwise. Load the specified 'result' with the name of the // current log file if file logging is enabled, and leave 'result' // unmodified otherwise. public: // TRAITS BSLMF_NESTED_TRAIT_DECLARATION(FileObserver2, bslma::UsesBslmaAllocator); // CREATORS explicit FileObserver2(bslma::Allocator *basicAllocator = 0); // Create a file observer with file logging initially disabled. // Optionally specify a 'basicAllocator' used to supply memory. If // 'basicAllocator' is 0, the currently installed default allocator is // used. Note that 'isPublishInLocalTimeEnabled' returns 'false' // following construction indicating that the timestamp attribute of // published records will be written in UTC time (see // 'enablePublishInLocalTime'). Also note that a default record format // is in effect for file logging (see 'setLogFileFunctor'). ~FileObserver2(); // Close the log file of this file observer if file logging is enabled, // and destroy this file observer. // MANIPULATORS void disableFileLogging(); // Disable file logging for this file observer. This method has no // effect if file logging is not enabled. Note that records // subsequently received through the 'publish' method will be dropped // until file logging is re-enabled. void disableLifetimeRotation(); // Disable log file rotation based on a periodic time interval for this // file observer. This method has no effect if // rotation-on-time-interval is not enabled. // // !DEPRECATED!: Use 'disableTimeIntervalRotation' instead. void disablePublishInLocalTime(); // Disable publishing of the timestamp attribute of records in local // time by this file observer; henceforth, timestamps will be in UTC // time. This method has no effect if publishing in local time is not // enabled. Note that this method also affects log filenames (see {Log // Filename Patterns}). void disableSizeRotation(); // Disable log file rotation based on log file size for this file // observer. This method has no effect if rotation-on-size is not // enabled. void disableTimeIntervalRotation(); // Disable log file rotation based on a periodic time interval for this // file observer. This method has no effect if // rotation-on-time-interval is not enabled. int enableFileLogging(const char *logFilenamePattern); // Enable logging of all records published to this file observer to a // file whose name is derived from the specified 'logFilenamePattern'. // Return 0 on success, a positive value if file logging is already // enabled (with no effect), and a negative value otherwise. The // basename of 'logFilenamePattern' may contain '%'-escape sequences // that are interpreted as follows: //.. // %Y - current year (4 digits with leading zeros) // %M - current month (2 digits with leading zeros) // %D - current day (2 digits with leading zeros) // %h - current hour (2 digits with leading zeros) // %m - current minute (2 digits with leading zeros) // %s - current second (2 digits with leading zeros) // %T - current datetime, equivalent to "%Y%M%D_%h%m%s" // %p - process ID //.. // Each time a log file is opened by this file observer (upon a // successful call to this method and following each log file // rotation), the name of the new log file is derived from // 'logFilenamePattern' by interpreting the above recognized '%'-escape // sequences. If 'isPublishInLocalTimeEnabled' returns 'true', the // '%'-escape sequences related to time will be substituted with local // time values, and UTC time values otherwise. See {Log Filename // Patterns}. int enableFileLogging(const char *logFilenamePattern, bool appendTimestampFlag); // Enable logging of all records published to this file observer to a // file whose name is derived from the specified 'logFilenamePattern' // and append a timestamp to the log filename if the specified // 'appendTimestampFlag' is 'true'. Return 0 on success, a positive // value if file logging is already enabled (with no effect), and a // negative value otherwise. If the 'appendTimestampFlag' is 'true' // and 'logFilenamePattern' does not contain any '%'-escape sequences, // this method behaves as if ".%T" is appended to 'logFilenamePattern'. // // !DEPRECATED!: Use 'enableFileLogging(logFilenamePattern)' instead // (use the ".%T" pattern to replicate 'true == appendTimestampFlag' // behavior). void enablePublishInLocalTime(); // Enable publishing of the timestamp attribute of records in local // time by this file observer. This method has no effect if publishing // in local time is already enabled. Note that this method also // affects log filenames (see {Log Filename Patterns}). void publish(const Record& record, const Context& context); // Process the specified log 'record' having the specified publishing // 'context' by writing 'record' and 'context' to the current log file // if file logging is enabled for this file observer. The method has // no effect if file logging is not enabled, in which case 'record' is // dropped. void publish(const bsl::shared_ptr<const Record>& record, const Context& context); // Process the record referenced by the specified 'record' shared // pointer having the specified publishing 'context' by writing the // record and 'context' to the current log file if file logging is // enabled for this file observer. The method has no effect if file // logging is not enabled, in which case 'record' is dropped. void releaseRecords(); // Discard any shared references to 'Record' objects that were supplied // to the 'publish' method, and are held by this observer. Note that // this operation should be called if resources underlying the // previously provided shared pointers must be released. void forceRotation(); // Forcefully perform a log file rotation by this file observer. Close // the current log file, rename the log file if necessary, and open a // new log file. This method has no effect if file logging is not // enabled. See {Rotated File Naming} for details on filenames of // rotated log files. void rotateOnSize(int size); // Set this file observer to perform log file rotation when the size of // the file exceeds the specified 'size' (in kilobytes). This rule // replaces any rotation-on-size rule currently in effect. The // behavior is undefined unless 'size > 0'. void rotateOnLifetime(const bdlt::DatetimeInterval& timeInterval); // Set this file observer to perform a periodic log file rotation at // multiples of the specified 'timeInterval'. This rule replaces any // rotation-on-time-interval rule currently in effect. The behavior is // undefined unless '0 < timeInterval.totalMilliseconds()'. // // !DEPRECATED!: Use 'rotateOnTimeInterval' instead. void rotateOnTimeInterval(const bdlt::DatetimeInterval& interval); void rotateOnTimeInterval(const bdlt::DatetimeInterval& interval, const bdlt::Datetime& startTime); // Set this file observer to perform a periodic log file rotation at // multiples of the specified 'interval'. Optionally specify a // 'startTime' indicating the datetime to use as the starting point for // computing the periodic rotation schedule. If // 'isPublishInLocalTimeEnabled' is 'true', the 'startTime' is // interpreted as local time, and as a UTC time otherwise. If // 'startTime' is not specified, the current time is used. This rule // replaces any rotation-on-time-interval rule currently in effect. // The behavior is undefined unless '0 < interval.totalMilliseconds()'. // Note that 'startTime' may be a fixed time in the past; e.g., a // reference time of 'bdlt::Datetime(1, 1, 1)' and an interval of 24 // hours would configure a periodic rotation at midnight each day. void setLogFileFunctor(const LogRecordFunctor& logFileFunctor); // Set the formatting functor used when writing records to the log file // of this file observer to the specified 'logFileFunctor'. Note that // a default format ("\n%d %p:%t %s %f:%l %c %m %u\n") is in effect // until this method is called (see 'ball_recordstringformatter'). // Also note that the observer emits newline characters at the // beginning and at the end of a log record by default, so the user // needs to add them explicitly to the format string to preserve this // behavior. void setOnFileRotationCallback( const OnFileRotationCallback& onRotationCallback); // Set the specified 'onRotationCallback' to be invoked after each time // this file observer attempts to perform a log file rotation. The // behavior is undefined if the supplied function calls either // 'setOnFileRotationCallback', 'forceRotation', or 'publish' on this // file observer (i.e., the supplied callback should *not* attempt to // write to the 'ball' log). void suppressUniqueFileNameOnRotation(bool suppress); // Suppress generating a unique log file name upon rotation if the // specified 'suppress' is 'true', and generate a unique filename // otherwise. See {Rotated File Naming} for details. // ACCESSORS bool isFileLoggingEnabled() const; bool isFileLoggingEnabled(bsl::string *result) const; bool isFileLoggingEnabled(std::string *result) const; // Return 'true' if file logging is enabled for this file observer, and // 'false' otherwise. Load the optionally specified 'result' with the // name of the current log file if file logging is enabled, and leave // 'result' unmodified otherwise. Note that records received through // the 'publish' method of this file observer will be dropped when this // method returns 'false'. #ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR bool isFileLoggingEnabled(std::pmr::string *result) const; // Return 'true' if file logging is enabled for this file observer, and // 'false' otherwise. Load the specified 'result' with the name of the // current log file if file logging is enabled, and leave 'result' // unmodified otherwise. #endif // BSLS_LIBRARYFEATURES_HAS_CPP17_PMR bool isPublishInLocalTimeEnabled() const; // Return 'true' if this file observer writes the timestamp attribute // of records that it publishes in local time, and 'false' otherwise // (in which case timestamps are written in UTC time). Note that the // value returned by this method also affects log filenames (see {Log // Filename Patterns}). bool isSuppressUniqueFileNameOnRotation() const; // Return 'true' if the log filename uniqueness check on rotation is // suppressed, and false otherwise. bdlt::DatetimeInterval rotationLifetime() const; // Return the lifetime of the log file that will trigger a file // rotation by this file observer if rotation-on-lifetime is in effect, // and a 0 time interval otherwise. int rotationSize() const; // Return the size (in kilobytes) of the log file that will trigger a // file rotation by this file observer if rotation-on-size is in // effect, and 0 otherwise. bdlt::DatetimeInterval localTimeOffset() const; // Return the difference between the local time and UTC time in effect // when this file observer was constructed. Note that this value // remains unchanged during the lifetime of this object and therefore // may become incorrect when the difference between the local time and // UTC time changes (e.g., when transitioning into or out of daylight // savings time). // // !DEPRECATED!: Use 'bdlt::LocalTimeOffset' instead. }; // ============================================================================ // INLINE DEFINITIONS // ============================================================================ // ------------------- // class FileObserver2 // ------------------- // MANIPULATORS inline void FileObserver2::publish(const bsl::shared_ptr<const Record>& record, const Context& context) { publish(*record, context); } inline void FileObserver2::releaseRecords() { } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2015 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------