Vault
4.1
|
00001 /* 00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved. 00003 This file is part of the Code Vault version 4.1 00004 http://www.bombaydigital.com/ 00005 License: MIT. See LICENSE.md in the Vault top level directory. 00006 */ 00007 00008 #ifndef vlogger_h 00009 #define vlogger_h 00010 00013 #include "vtypes.h" 00014 00015 #include "vmutex.h" 00016 #include "vbufferedfilestream.h" 00017 #include "vtextiostream.h" 00018 00019 // Microsoft steals this symbol name globally. Take it back. 00020 #ifdef VPLATFORM_WIN 00021 #undef ERROR 00022 #endif 00023 // Xcode 5 steals this symbol name globally. Take it back. 00024 #ifdef VPLATFORM_MAC 00025 #undef DEBUG 00026 #endif 00027 00028 class VSettings; 00029 class VSettingsNode; 00030 class VBentoNode; 00031 00214 // This first set of macros sends output to the default logger. 00215 #define VLOGGER_LEVEL(level, message) do { if (!VLogger::isDefaultLogLevelActive(level)) break; VLogger::getDefaultLogger()->log(level, NULL, 0, message, VString::EMPTY()); } while (false) 00216 #define VLOGGER_LEVEL_FILELINE(level, message, file, line) do { if (!VLogger::isDefaultLogLevelActive(level)) break; VLogger::getDefaultLogger()->log(level, file, line, message, VString::EMPTY()); } while (false) 00217 #define VLOGGER_LINE(level, message) VLOGGER_LEVEL_FILELINE(level, message, __FILE__, __LINE__) 00218 #define VLOGGER_FATAL_AND_THROW(message) do { VLogger::getDefaultLogger()->log(VLoggerLevel::FATAL, __FILE__, __LINE__, message); throw VStackTraceException(message); } while (false) 00219 #define VLOGGER_FATAL(message) VLOGGER_LEVEL_FILELINE(VLoggerLevel::FATAL, message, __FILE__, __LINE__) 00220 #define VLOGGER_ERROR(message) VLOGGER_LEVEL_FILELINE(VLoggerLevel::ERROR, message, __FILE__, __LINE__) 00221 #define VLOGGER_WARN(message) VLOGGER_LEVEL(VLoggerLevel::WARN, message) 00222 #define VLOGGER_INFO(message) VLOGGER_LEVEL(VLoggerLevel::INFO, message) 00223 #define VLOGGER_DEBUG(message) VLOGGER_LEVEL(VLoggerLevel::DEBUG, message) 00224 #define VLOGGER_TRACE(message) VLOGGER_LEVEL(VLoggerLevel::TRACE, message) 00225 #define VLOGGER_HEXDUMP(level, message, buffer, length) do { if (!VLogger::isDefaultLogLevelActive(level)) break; VLogger::getDefaultLogger()->logHexDump(level, message, VString::EMPTY(), buffer, length); } while (false) 00226 #define VLOGGER_WOULD_LOG(level) (VLogger::isDefaultLogLevelActive(level)) 00227 00228 // This set of macros sends output to a specified named logger. 00229 #define VLOGGER_NAMED_LEVEL(loggername, level, message) do { if (!VLogger::isLogLevelActive(level)) break; VNamedLoggerPtr nl = VLogger::findNamedLoggerForLevel(loggername, level); if (nl != nullptr) nl->log(level, NULL, 0, message, loggername); } while (false) 00230 #define VLOGGER_NAMED_LEVEL_FILELINE(loggername, level, message, file, line) do { if (!VLogger::isLogLevelActive(level)) break; VNamedLoggerPtr nl = VLogger::findNamedLoggerForLevel(loggername, level); if (nl != nullptr) nl->log(level, file, line, message, loggername); } while (false) 00231 #define VLOGGER_NAMED_LINE(loggername, level, message) VLOGGER_NAMED_LEVEL_FILELINE(loggername, level, message, __FILE__, __LINE__) 00232 #define VLOGGER_NAMED_FATAL(loggername, message) VLOGGER_NAMED_LEVEL_FILELINE(loggername, VLoggerLevel::FATAL, message, __FILE__, __LINE__) 00233 #define VLOGGER_NAMED_ERROR(loggername, message) VLOGGER_NAMED_LEVEL_FILELINE(loggername, VLoggerLevel::ERROR, message, __FILE__, __LINE__) 00234 #define VLOGGER_NAMED_WARN(loggername, message) VLOGGER_NAMED_LEVEL(loggername, VLoggerLevel::WARN, message) 00235 #define VLOGGER_NAMED_INFO(loggername, message) VLOGGER_NAMED_LEVEL(loggername, VLoggerLevel::INFO, message) 00236 #define VLOGGER_NAMED_DEBUG(loggername, message) VLOGGER_NAMED_LEVEL(loggername, VLoggerLevel::DEBUG, message) 00237 #define VLOGGER_NAMED_TRACE(loggername, message) VLOGGER_NAMED_LEVEL(loggername, VLoggerLevel::TRACE, message) 00238 #define VLOGGER_NAMED_HEXDUMP(loggername, level, message, buffer, length) do { if (!VLogger::isLogLevelActive(level)) break; VNamedLoggerPtr nl = VLogger::findNamedLoggerForLevel(loggername, level); if (nl != nullptr) nl->logHexDump(level, message, loggername, buffer, length); } while (false) 00239 #define VLOGGER_NAMED_WOULD_LOG(loggername, level) (VLogger::isLogLevelActive(level) && (VLogger::findNamedLoggerForLevel(loggername, level) != nullptr)) 00240 00241 #define VLOGGER_APPENDER_EMIT(appender, level, message) do { (appender).emit(level, (level <= VLoggerLevel::ERROR) ? __FILE__ : NULL, (level <= VLoggerLevel::ERROR) ? __LINE__ : 0, true, message, VString::EMPTY(), VString::EMPTY(), false, VString::EMPTY()); } while (false) 00242 #define VLOGGER_APPENDER_EMIT_FILELINE(appender, level, message, file, line) do { (appender).emit(level, file, line, true, message, VString::EMPTY(), VString::EMPTY(), false, VString::EMPTY()); } while (false) 00243 00247 class VLogAppender { 00248 public: 00249 00250 // These constants can be used for the formatOutput constructor parameter. 00251 static const bool DO_FORMAT_OUTPUT = true; 00252 static const bool DONT_FORMAT_OUTPUT = false; 00253 00262 VLogAppender(const VString& name, bool formatOutput, const VString& formatSpec, const VString& timeFormat); 00269 VLogAppender(const VSettingsNode& settings, const VSettingsNode& defaults); 00270 00271 virtual ~VLogAppender(); 00272 00273 const VString& getName() const { return mName; } 00274 bool isDefaultAppender() const; 00275 00300 virtual void emit(int level, const char* file, int line, bool emitMessage, const VString& message, const VString& specifiedLoggerName, const VString& actualLoggerName, bool emitRawLine, const VString& rawLine); 00305 void emitRaw(const VString& message); 00306 00312 virtual void addInfo(VBentoNode& infoNode) const; 00313 00314 protected: 00315 00327 virtual void _emitMessage(int level, const char* file, int line, const VString& message, const VString& specifiedLoggerName, const VString& actualLoggerName); 00342 virtual VString _formatMessage(int level, const char* file, int line, const VString& message, const VString& specifiedLoggerName, const VString& actualLoggerName); 00350 virtual void _emitRawLine(const VString& /*line*/) {} 00351 00352 // These helper functions are meant to be used by subclasses constructing from settings. 00353 // Such constructors usually need to get settings, and fall back first to configured defaults, then to a specific default value. 00354 static bool _getBooleanInitSetting(const VString& attributePath, const VSettingsNode& settings, const VSettingsNode& defaults, bool defaultValue); 00355 static int _getIntInitSetting(const VString& attributePath, const VSettingsNode& settings, const VSettingsNode& defaults, int defaultValue); 00356 static VString _getStringInitSetting(const VString& attributePath, const VSettingsNode& settings, const VSettingsNode& defaults, const VString& defaultValue); 00357 00358 VMutex mMutex; 00359 // subclasses may access this carefully; note that it is locked prior to any 00360 // call to emitMessage() or emitRawLine(), so implementors of those functions must 00361 // not re-lock because to do so would cause a deadlock. 00362 VString mName; 00363 bool mFormatOutput; 00364 VString mFormatSpec; 00365 VInstantFormatter mTimeFormatter; 00366 00367 // These fields cache state of the mFormatSpec. This allows _formatMessage() to avoid unnecessary work 00368 // when we know the format doesn't need everything to be supplied. If we allow mFormatSpec to be set 00369 // after construction, these will have to be re-calculated at that time. 00370 bool mFormatUsesLocalTime; 00371 bool mFormatUsesUTCTime; 00372 bool mFormatUsesLevel; 00373 bool mFormatUsesThread; 00374 bool mFormatUsesLocation; 00375 bool mFormatUsesSpecifiedLoggerName; 00376 bool mFormatUsesActualLoggerName; 00377 00378 private: 00379 00380 VString _toString() const; 00381 00382 static void _breakpointLocationForEmit(); 00383 }; 00384 00385 typedef VSharedPtr<VLogAppender> VLogAppenderPtr; 00386 typedef VSharedPtr<const VLogAppender> VLogAppenderConstPtr; 00387 typedef std::vector<VLogAppenderPtr> VLogAppenderPtrList; 00388 00389 class VNamedLogger; 00390 00397 class VLoggerRepetitionFilter { 00398 public: 00399 00400 VLoggerRepetitionFilter(); 00401 virtual ~VLoggerRepetitionFilter() {} 00402 00408 void setEnabled(bool enabled) { mEnabled = enabled; } 00413 bool isEnabled() const { return mEnabled; } 00414 00419 void reset(); 00420 00435 bool checkMessage(VNamedLogger& logger, int level, const char* file, int line, const VString& message, const VString& specifiedLoggerName, const VString& actualLoggerName); 00436 00444 void checkTimeout(VNamedLogger& logger); 00445 00446 private: 00447 00448 VLoggerRepetitionFilter(const VLoggerRepetitionFilter&); // not copyable 00449 VLoggerRepetitionFilter& operator=(const VLoggerRepetitionFilter&); // not assignable 00450 00456 void _emitSuppressedMessages(VNamedLogger& logger); 00457 00458 bool mEnabled; 00459 00460 // Information defining the saved output. The (level, file, line, message) combination 00461 // defines a repeated message. If any of those differ, then it's considered a different 00462 // message that is not a repeat. 00463 bool mHasSavedMessage; 00464 int mNumSuppressedOccurrences; 00465 VInstant mTimeOfLastOccurrence; 00466 int mLevel; 00467 const char* mFile; 00468 int mLine; 00469 VString mMessage; 00470 VString mSpecifiedLoggerName; 00471 VString mActualLoggerName; 00472 }; 00473 00478 class VLoggerPrintStackConfig { 00479 public: 00480 00481 VLoggerPrintStackConfig(); 00482 ~VLoggerPrintStackConfig() {} 00483 00484 int getLevel() const { return mLevel; } 00485 void configure(int level, int maxNumOccurrences, const VDuration& timeLimit); 00486 bool shouldPrintStack(int level, VNamedLogger& logger); 00487 00488 private: 00489 00490 int mLevel; 00491 int mMaxCount; 00492 VDuration mDuration; 00493 int mCountdown; 00494 VInstant mExpiration; 00495 }; 00496 00509 class VNamedLogger : public VEnableSharedFromThis<VNamedLogger> { 00510 public: 00511 00521 VNamedLogger(const VString& name, int level, const VStringVector& appenderNames, VLogAppenderPtr specificAppender = VLogAppenderPtr()); 00522 virtual ~VNamedLogger(); 00523 00527 void clearAppenders(); 00532 void setAppender(const VString& appenderName); 00537 void addAppender(const VString& appenderName); 00538 00539 // The following log/emit APIs should generally be accessed through the VLOGGER macros. 00540 // However, it is legal to call them if you have a reference to a logger. 00541 00551 void log(int level, const char* file, int line, const VString& message, const VString& specifiedLoggerName = VString::EMPTY()); 00557 void log(int level, const VString& message); 00566 void logHexDump(int level, const VString& message, const VString& specifiedLoggerName, const Vu8* buffer, Vs64 length); 00571 void emitStackCrawlLine(const VString& message); 00572 00573 const VString& getName() const { return mName; } 00574 bool isEnabledFor(int level) { return level <= mLevel; } 00575 int getLevel() const { return mLevel; } 00576 void setLevel(int level); 00577 00578 void setRepetitionFilterEnabled(bool enabled) { mRepetitionFilter.setEnabled(enabled); } 00579 00586 int getPrintStackLevel() const { return mPrintStackConfig.getLevel(); } 00593 void setPrintStackInfo(int printStackLevel, int maxNumOccurrences, const VDuration& timeLimit) { mPrintStackConfig.configure(printStackLevel, maxNumOccurrences, timeLimit); } 00598 bool isDefaultLogger() const; 00599 00605 virtual void addInfo(VBentoNode& infoNode) const; 00606 00607 protected: 00608 00621 virtual void _emitToAppenders(int level, const char* file, int line, bool emitMessage, const VString& message, const VString& specifiedLoggerName, bool emitRawLine, const VString& rawLine); 00622 00623 private: 00624 00625 VString _toString() const; 00626 00627 static void _breakpointLocationForLog(); 00628 00629 VString mName; 00630 int mLevel; 00631 mutable VMutex mAppendersMutex; 00632 VStringVector mAppenderNames; 00633 VLogAppenderPtr mSpecificAppender; 00634 VLoggerRepetitionFilter mRepetitionFilter; 00635 VLoggerPrintStackConfig mPrintStackConfig; 00636 00637 friend class VLoggerRepetitionFilter; // it can call our _emitToAppenders when we call it from our log() function 00638 friend class VLoggerPrintStackConfig; // ditto 00639 }; 00640 00641 typedef VSharedPtr<VNamedLogger> VNamedLoggerPtr; 00642 typedef VSharedPtr<const VNamedLogger> VNamedLoggerConstPtr; 00643 00648 class VLogAppenderFactory { 00649 public: 00650 00651 VLogAppenderFactory() {} 00652 virtual ~VLogAppenderFactory() {} 00653 00659 virtual VLogAppenderPtr instantiateLogAppender(const VSettingsNode& settings, const VSettingsNode& defaults) const = 0; 00660 00667 virtual void addInfo(VBentoNode& infoNode) const = 0; 00668 00669 }; 00670 00671 typedef VSharedPtr<const VLogAppenderFactory> VLogAppenderFactoryPtr; 00672 00679 class VLoggerLevel { 00680 public: 00681 00682 // Log level constants. 00683 static const int OFF = 0; 00684 static const int FATAL = 1; 00685 static const int ERROR = 20; 00686 static const int WARN = 40; 00687 static const int INFO = 60; 00688 static const int DEBUG = 80; 00689 static const int TRACE = 100; 00690 static const int ALL = 100; 00691 00701 static VString getName(int level); 00710 static int fromString(const VString& value); 00711 }; 00712 00718 class VLogger { 00719 public: 00720 00730 static void registerLogAppenderFactory(const VString& appenderKind, VLogAppenderFactoryPtr factory); 00731 00752 static void configure(const VFSNode& baseLogDirectory, const VSettingsNode& loggingSettings); 00758 static void shutdown(); 00759 00768 static void installNewLogAppender(const VSettingsNode& appenderSettings, const VSettingsNode& appenderDefaults); 00775 static void installNewNamedLogger(const VSettingsNode& loggerSettings); 00784 static void installNewNamedLogger(const VString& name, int level, const VStringVector& appenderNames); 00793 static void installNewNamedLogger(const VString& name, int level, const VString& appenderName); 00800 static void registerLogAppender(VLogAppenderPtr appender, bool asDefaultAppender = false); 00808 static void registerGlobalAppender(VLogAppenderPtr appender, bool asDefaultAppender = false); 00815 static void registerLogger(VNamedLoggerPtr namedLogger, bool asDefaultLogger = false); 00820 static void deregisterLogAppender(VLogAppenderPtr appender); 00825 static void deregisterLogAppender(const VString& name); 00830 static void deregisterLogger(VNamedLoggerPtr namedLogger); 00835 static void deregisterLogger(const VString& name); 00840 static void checkMaxActiveLogLevelForRemovedLogger(int removedActiveLevel); 00846 static void checkMaxActiveLogLevelForChangedLogger(int oldActiveLevel, int newActiveLevel); 00847 00853 static bool isDefaultLogLevelActive(int level); 00859 static bool isLogLevelActive(int level); 00860 00861 // The following "getters" and "finders" have the following consistent naming convention: 00862 // - "get" always returns a valid object; it may need to create the object in question 00863 // - "find" will return null if there is no such object; it will not create an object 00864 00865 // Loggers: 00870 static VNamedLoggerPtr getDefaultLogger(); 00875 static void setDefaultLogger(VNamedLoggerPtr namedLogger); 00882 static VNamedLoggerPtr getLogger(const VString& name); 00887 static VNamedLoggerPtr findDefaultLogger(); 00893 static VNamedLoggerPtr findDefaultLoggerForLevel(int level); 00899 static VNamedLoggerPtr findNamedLogger(const VString& name); 00906 static VNamedLoggerPtr findNamedLoggerForLevel(const VString& name, int level); 00907 00908 // Appenders: 00913 static VLogAppenderPtr getDefaultAppender(); 00920 static VLogAppenderPtr getAppender(const VString& appenderName); 00926 static VLogAppenderPtrList getAllAppenders(); 00931 static VLogAppenderPtr findDefaultAppender(); 00937 static VLogAppenderPtr findAppender(const VString& name); 00942 static const VFSNode& getBaseLogDirectory(); 00943 00944 // These functions whose name is prefixed with "command" are intended for use at runtime from 00945 // a command facility that allows reconfiguring logging on the fly. 00946 static VBentoNode* commandGetInfo(); 00947 static VString commandGetInfoString(); 00948 static void commandNewAppender(const VString& appenderName, const VString& kind, const VString& appenderParam); 00949 static void commandRemoveAppender(const VString& appenderName); 00950 static void commandRollAppender(const VString& appenderName); 00951 static void commandNewLogger(const VString& loggerName, const VStringVector& appenderNames); 00952 static void commandRemoveLogger(const VString& loggerName); 00953 static void commandSetLoggerAppenders(const VString& loggerName, const VStringVector& appenderNames); 00954 static void commandAddLoggerAppenders(const VString& loggerName, const VStringVector& appenderNames); 00955 static void commandRemoveLoggerAppenders(const VString& loggerName, const VStringVector& appenderNames); 00956 static void commandSetLogLevel(const VString& loggerName, int level); 00957 static void commandSetPrintStackLevel(const VString& loggerName, int printStackLevel, int count, const VDuration& timeLimit); 00958 00959 // Used specifically by VNamedLogger::_emitToAppenders to emit to all "global appenders" with correct locking. Should not be called elsewhere. 00960 static void emitToGlobalAppenders(int level, const char* file, int line, bool emitMessage, const VString& message, const VString& specifiedLoggerName, const VString& actualLoggerName, bool emitRawLine, const VString& rawLine); 00961 00962 // Utility function useful in forming a logger name; returns a copy of the input string with dots (our path separators) converted to dashes. 00963 static VString getCleansedLoggerName(const VString& s); 00964 00965 private: 00966 00967 VLogger(const VLogger&); // not copyable 00968 VLogger& operator=(const VLogger&); // not assignable 00969 00970 // These helper methods, like private methods in general, assume the caller has locked. 00971 static void _registerAppender(VLogAppenderPtr appender, bool asDefaultAppender = false, bool asGlobalAppender = false); 00972 static void _registerLogger(VNamedLoggerPtr namedLogger, bool asDefaultLogger = false); 00973 static VBentoNode* _commandGetInfo(); 00974 static VString _commandGetInfoString(); 00975 00976 // These methods maintain the gMaxActiveLogLevel. 00977 static void _checkMaxActiveLogLevelForNewLogger(int newActiveLevel); // Called when a new logger is created, since that may change the max active log level. 00978 static void _checkMaxActiveLogLevelForRemovedLogger(int removedActiveLevel); // Called when a logger is removed, since that may change the max active log level. 00979 static void _checkMaxActiveLogLevelForChangedLogger(int oldActiveLevel, int newActiveLevel); // Called when a logger's level is changed, since that may change the max active log level. 00980 static void _recalculateMaxActiveLogLevel(); // Called when one of the _check... methods decides the max active log level may indeed have changed, and must be recalculated. 00981 00982 // These two methods are how we really search for a specified named logger. 00983 static VNamedLoggerPtr _findNamedLoggerFromExactName(const VString& name); 00984 static VNamedLoggerPtr _findNamedLoggerFromPathName(const VString& pathName); 00985 00986 // _mutexInstance() must be used internally whenever referencing these variables: 00987 volatile static int gMaxActiveLevel; 00988 static VNamedLoggerPtr gDefaultLogger; 00989 static VLogAppenderPtr gDefaultAppender; 00990 static VFSNode gBaseLogDirectory; 00991 00992 friend class VLoggerUnit; // unit tests directly examine our state 00993 friend bool VNamedLogger::isDefaultLogger() const; 00994 friend bool VLogAppender::isDefaultAppender() const; 00995 00996 // Internal development debugging methods. Only enabled as needed. 00997 //#define VLOGGER_INTERNAL_DEBUGGING 00998 #ifdef VLOGGER_INTERNAL_DEBUGGING 00999 static void _reportLoggerChange(bool before, const VString& label, const VNamedLoggerPtr& was, const VNamedLoggerPtr& is); 01000 static void _reportAppenderChange(bool before, const VString& label, const VLogAppenderPtr& was, const VLogAppenderPtr& is); 01001 #else 01002 static void _reportLoggerChange(bool /*before*/, const VString& /*label*/, const VNamedLoggerPtr& /*was*/, const VNamedLoggerPtr& /*is*/) {} 01003 static void _reportAppenderChange(bool /*before*/, const VString& /*label*/, const VLogAppenderPtr& /*was*/, const VLogAppenderPtr& /*is*/) {} 01004 #endif /* VLOGGER_INTERNAL_DEBUGGING */ 01005 }; 01006 01011 class VCoutLogAppender : public VLogAppender { 01012 public: 01013 VCoutLogAppender(const VString& name, bool formatOutput, const VString& formatSpec, const VString& timeFormat); 01014 VCoutLogAppender(const VSettingsNode& settings, const VSettingsNode& defaults); 01015 virtual ~VCoutLogAppender() {} 01016 virtual void addInfo(VBentoNode& infoNode) const; 01017 protected: 01018 virtual void _emitRawLine(const VString& line); 01019 }; 01020 01027 class VFileLogAppender : public VLogAppender { 01028 public: 01029 VFileLogAppender(const VString& name, bool formatOutput, const VString& formatSpec, const VString& timeFormat, const VString& filePath); 01030 VFileLogAppender(const VSettingsNode& settings, const VSettingsNode& defaults); 01031 virtual ~VFileLogAppender() {} 01032 virtual void addInfo(VBentoNode& infoNode) const; 01033 protected: 01034 virtual void _emitRawLine(const VString& line); 01035 private: 01036 void _openFile(); // constructor helper 01037 VBufferedFileStream mFileStream; 01038 VTextIOStream mOutputStream; 01039 }; 01040 01052 class VRollingFileLogAppender : public VLogAppender { 01053 public: 01054 VRollingFileLogAppender(const VString& name, bool formatOutput, const VString& formatSpec, const VString& timeFormat, const VString& dirPath, const VString& fileNamePrefix, int maxNumLines); 01055 VRollingFileLogAppender(const VSettingsNode& settings, const VSettingsNode& defaults); 01056 virtual ~VRollingFileLogAppender() {} 01057 virtual void addInfo(VBentoNode& infoNode) const; 01058 protected: 01059 virtual void _emitRawLine(const VString& line); 01060 }; 01061 01066 class VSilentLogAppender : public VLogAppender { 01067 public: 01068 VSilentLogAppender(const VString& name) : VLogAppender(name, true/*this won't matter*/, VString::EMPTY(), VString::EMPTY()) {} 01069 VSilentLogAppender(const VSettingsNode& settings, const VSettingsNode& defaults) : VLogAppender(settings, defaults) {} 01070 virtual ~VSilentLogAppender() {} 01071 virtual void addInfo(VBentoNode& infoNode) const; 01072 virtual void emit(int /*level*/, const char* /*file*/, int /*line*/, bool /*emitMessage*/, const VString& /*message*/, bool /*emitRawLine*/, const VString& /*rawLine*/) {} 01073 }; 01074 01082 class VStringLogAppender : public VLogAppender { 01083 public: 01084 VStringLogAppender(const VString& name, bool formatOutput, const VString& formatSpec, const VString& timeFormat); 01085 VStringLogAppender(const VSettingsNode& settings, const VSettingsNode& defaults); 01086 virtual ~VStringLogAppender() {} 01087 virtual void addInfo(VBentoNode& infoNode) const; 01088 01089 VMutex& getMutex() { return mMutex; } 01090 const VString& getLines() const { return mLines; } 01091 const char* orphanLines() { return mLines.orphanDataBuffer(); } 01092 01093 protected: 01094 virtual void _emitRawLine(const VString& line); 01095 private: 01096 VString mLines; 01097 }; 01098 01105 class VStringVectorLogAppender : public VLogAppender { 01106 public: 01107 VStringVectorLogAppender(const VString& name, bool formatOutput, const VString& formatSpec, const VString& timeFormat, VStringVector* storage); 01108 VStringVectorLogAppender(const VSettingsNode& settings, const VSettingsNode& defaults); 01109 virtual ~VStringVectorLogAppender(); 01110 virtual void addInfo(VBentoNode& infoNode) const; 01111 01112 VMutex& getMutex() { return mMutex; } 01113 const VStringVector& getLines() const { return *mStorage; } 01114 01115 protected: 01116 virtual void _emitRawLine(const VString& line); 01117 private: 01118 VStringVector* mStorage; 01119 VStringVector mLines; 01120 }; 01121 01126 class VStringLogger : public VNamedLogger { 01127 public: 01128 01129 VStringLogger(const VString& name, int level, bool formatOutput = VLogAppender::DO_FORMAT_OUTPUT, const VString& formatSpec = VString::EMPTY(), const VString& timeFormat = VString::EMPTY()); 01130 virtual ~VStringLogger() {} 01131 virtual void addInfo(VBentoNode& infoNode) const; 01132 01133 const VString& getLines() const { return mAppender.getLines(); } 01134 const char* orphanLines() { return mAppender.orphanLines(); } 01135 01136 protected: 01137 01138 virtual void _emitToAppenders(int level, const char* file, int line, bool emitMessage, const VString& message, const VString& specifiedLoggerName, bool emitRawLine, const VString& rawLine); 01139 01140 private: 01141 01142 VStringLogAppender mAppender; 01143 01144 }; 01145 01146 typedef VSharedPtr<VStringLogger> VStringLoggerPtr; 01147 typedef VSharedPtr<const VStringLogger> VStringLoggerConstPtr; 01148 01153 class VStringVectorLogger : public VNamedLogger { 01154 public: 01155 01156 VStringVectorLogger(const VString& name, int level, VStringVector* storage, bool formatOutput = VLogAppender::DO_FORMAT_OUTPUT, const VString& formatSpec = VString::EMPTY(), const VString& timeFormat = VString::EMPTY()); 01157 virtual ~VStringVectorLogger() {} 01158 virtual void addInfo(VBentoNode& infoNode) const; 01159 01160 const VStringVector& getLines() const { return mAppender.getLines(); } 01161 01162 protected: 01163 01164 virtual void _emitToAppenders(int level, const char* file, int line, bool emitMessage, const VString& message, const VString& specifiedLoggerName, bool emitRawLine, const VString& rawLine); 01165 01166 private: 01167 01168 VStringVectorLogAppender mAppender; 01169 01170 }; 01171 01172 typedef VSharedPtr<VStringVectorLogger> VStringVectorLoggerPtr; 01173 typedef VSharedPtr<const VStringVectorLogger> VStringVectorLoggerConstPtr; 01174 01175 #endif /* vlogger_h */