diff options
author | Eric Tulla <tulla@lindenlab.com> | 2008-05-14 21:37:13 +0000 |
---|---|---|
committer | Eric Tulla <tulla@lindenlab.com> | 2008-05-14 21:37:13 +0000 |
commit | e77de5d685ae441f72920f0e04d9887ee958745a (patch) | |
tree | b3736831042b20be198dc9994ba68db1e8be2a14 /indra/llcommon | |
parent | 41e1ed5b4153019b07d97f54751db53fa248d8d4 (diff) |
Result of svn merge -r 87455:87538 $SVN/branches/tulla/vc3-merge .
Passed QA as part of QAR-491.
Diffstat (limited to 'indra/llcommon')
-rw-r--r-- | indra/llcommon/llapr.cpp | 12 | ||||
-rw-r--r-- | indra/llcommon/llerror.cpp | 69 | ||||
-rw-r--r-- | indra/llcommon/llerror.h | 82 | ||||
-rw-r--r-- | indra/llcommon/lltimer.cpp | 5 | ||||
-rw-r--r-- | indra/llcommon/lltimer.h | 4 |
5 files changed, 130 insertions, 42 deletions
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 5e6dfd975e..5be3919898 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -54,7 +54,7 @@ void ll_init_apr() void ll_cleanup_apr() { - llinfos << "Cleaning up APR" << llendl; + LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL; if (gLogMutexp) { @@ -118,7 +118,7 @@ bool ll_apr_warn_status(apr_status_t status) if(APR_SUCCESS == status) return false; #ifndef LL_WINDOWS char buf[MAX_STRING]; /* Flawfinder: ignore */ - llwarns << "APR: " << apr_strerror(status, buf, MAX_STRING) << llendl; + LL_WARNS_ONCE("APR") << "APR: " << apr_strerror(status, buf, MAX_STRING) << LL_ENDL; #endif return true; } @@ -294,7 +294,7 @@ bool ll_apr_file_remove(const LLString& filename, apr_pool_t* pool) s = apr_file_remove(filename.c_str(), pool); if (s != APR_SUCCESS) { - lldebugs << "ll_apr_file_remove failed on file: " << filename << llendl; + LL_DEBUGS("APR") << "ll_apr_file_remove failed on file: " << filename << LL_ENDL; ll_apr_warn_status(s); return false; } @@ -308,7 +308,7 @@ bool ll_apr_file_rename(const LLString& filename, const LLString& newname, apr_p s = apr_file_rename(filename.c_str(), newname.c_str(), pool); if (s != APR_SUCCESS) { - lldebugs << "ll_apr_file_rename failed on file: " << filename << llendl; + LL_DEBUGS("APR") << "ll_apr_file_rename failed on file: " << filename << LL_ENDL; ll_apr_warn_status(s); return false; } @@ -365,7 +365,7 @@ bool ll_apr_dir_make(const LLString& dirname, apr_pool_t* pool) s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool); if (s != APR_SUCCESS) { - lldebugs << "ll_apr_dir_make failed on file: " << dirname << llendl; + LL_DEBUGS("APR") << "ll_apr_dir_make failed on file: " << dirname << LL_ENDL; ll_apr_warn_status(s); return false; } @@ -379,7 +379,7 @@ bool ll_apr_dir_remove(const LLString& dirname, apr_pool_t* pool) s = apr_file_remove(dirname.c_str(), pool); if (s != APR_SUCCESS) { - lldebugs << "ll_apr_dir_remove failed on file: " << dirname << llendl; + LL_DEBUGS("APR") << "ll_apr_dir_remove failed on file: " << dirname << LL_ENDL; ll_apr_warn_status(s); return false; } diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 13bf368334..e635011941 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -408,6 +408,8 @@ namespace LLError LevelMap functionLevelMap; LevelMap classLevelMap; LevelMap fileLevelMap; + LevelMap tagLevelMap; + std::map<std::string, unsigned int> uniqueLogMessages; LLError::FatalFunction crashFunction; LLError::TimeFunction timeFunction; @@ -494,11 +496,17 @@ namespace LLError namespace LLError { CallSite::CallSite(ELevel level, - const char* file, int line, - const std::type_info& class_info, const char* function) + const char* file, + int line, + const std::type_info& class_info, + const char* function, + const char* broadTag, + const char* narrowTag, + bool printOnce) : mLevel(level), mFile(file), mLine(line), mClassInfo(class_info), mFunction(function), - mCached(false), mShouldLog(false) + mCached(false), mShouldLog(false), + mBroadTag(broadTag), mNarrowTag(narrowTag), mPrintOnce(printOnce) { } @@ -552,6 +560,15 @@ namespace #endif LogControlFile& e = LogControlFile::fromDirectory(dir); + + // NOTE: We want to explicitly load the file before we add it to the event timer + // that checks for changes to the file. Else, we're not actually loading the file yet, + // and most of the initialization happens without any attention being paid to the + // log control file. Not to mention that when it finally gets checked later, + // all log statements that have been evaluated already become dirty and need to be + // evaluated for printing again. So, make sure to call checkAndReload() + // before addToEventTimer(). + e.checkAndReload(); e.addToEventTimer(); } } @@ -625,6 +642,14 @@ namespace LLError g.invalidateCallSites(); s.fileLevelMap[file_name] = level; } + + void setTagLevel(const std::string& tag_name, ELevel level) + { + Globals& g = Globals::get(); + Settings& s = Settings::get(); + g.invalidateCallSites(); + s.tagLevelMap[tag_name] = level; + } } namespace { @@ -674,6 +699,8 @@ namespace LLError s.functionLevelMap.clear(); s.classLevelMap.clear(); s.fileLevelMap.clear(); + s.tagLevelMap.clear(); + s.uniqueLogMessages.clear(); setPrintLocation(config["print-location"]); setDefaultLevel(decodeLevel(config["default-level"])); @@ -689,6 +716,7 @@ namespace LLError setLevels(s.functionLevelMap, entry["functions"], level); setLevels(s.classLevelMap, entry["classes"], level); setLevels(s.fileLevelMap, entry["files"], level); + setLevels(s.tagLevelMap, entry["tags"], level); } } } @@ -850,7 +878,7 @@ namespace { return false; } - level = i->second; + level = i->second; return true; } @@ -929,9 +957,15 @@ namespace LLError ELevel compareLevel = s.defaultLevel; - checkLevelMap(s.functionLevelMap, function_name, compareLevel) + // The most specific match found will be used as the log level, + // since the computation short circuits. + // So, in increasing order of importance: + // Default < Broad Tag < File < Class < Function < Narrow Tag + ((site.mNarrowTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mNarrowTag, compareLevel) : false) + || checkLevelMap(s.functionLevelMap, function_name, compareLevel) || checkLevelMap(s.classLevelMap, class_name, compareLevel) - || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel); + || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel) + || ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false); site.mCached = true; g.addCallSite(site); @@ -1018,6 +1052,29 @@ namespace LLError #endif prefix << site.mFunction << ": "; } + + if (site.mPrintOnce) + { + std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message); + if (messageIter != s.uniqueLogMessages.end()) + { + messageIter->second++; + unsigned int num_messages = messageIter->second; + if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0) + { + prefix << "ONCE (" << num_messages << "th time seen): "; + } + else + { + return; + } + } + else + { + prefix << "ONCE: "; + s.uniqueLogMessages[message] = 1; + } + } prefix << message; message = prefix.str(); diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index ae41cd5244..13fb2bcebe 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -45,23 +45,23 @@ Code can log messages with constuctions like this: - llinfos << "request to fizzbip agent " << agent_id - << " denied due to timeout" << llendl; + LL_INFOS("StringTag") << "request to fizzbip agent " << agent_id + << " denied due to timeout" << LL_ENDL; Messages can be logged to one of four increasing levels of concern, using one of four "streams": - lldebugs - debug messages that are normally supressed - llinfos - informational messages that are normall shown - llwarns - warning messages that singal a problem - llerrs - error messages that are major, unrecoverable failures + LL_DEBUGS("StringTag") - debug messages that are normally supressed + LL_INFOS("StringTag") - informational messages that are normall shown + LL_WARNS("StringTag") - warning messages that singal a problem + LL_ERRS("StringTag") - error messages that are major, unrecoverable failures - The later (llerrs) automatically crashes the process after the message + The later (LL_ERRS("StringTag")) automatically crashes the process after the message is logged. Note that these "streams" are actually #define magic. Rules for use: * they cannot be used as normal streams, only to start a message - * messages written to them MUST be terminated with llendl + * messages written to them MUST be terminated with LL_ENDL * between the opening and closing, the << operator is indeed writing onto a std::ostream, so all conversions and stream formating are available @@ -85,7 +85,7 @@ { if (i > 100) { - llwanrs << "called with a big value for i: " << i << llendl; + LL_WARNS("FooBarTag") << "called with a big value for i: " << i << LL_ENDL; } ... } @@ -100,7 +100,7 @@ Lastly, logging is now very efficient in both compiled code and execution when skipped. There is no need to wrap messages, even debugging ones, in - #ifdef _DEBUG constructs. lldebugs messages are compiled into all builds, + #ifdef _DEBUG constructs. LL_DEBUGS("StringTag") messages are compiled into all builds, even release. Which means you can use them to help debug even when deployed to a real grid. */ @@ -144,7 +144,7 @@ namespace LLError // intended for public use. public: CallSite(ELevel, const char* file, int line, - const std::type_info& class_info, const char* function); + const std::type_info& class_info, const char* function, const char* broadTag, const char* narrowTag, bool printOnce); bool shouldLog() { return mCached ? mShouldLog : Log::shouldLog(*this); } @@ -156,9 +156,12 @@ namespace LLError // these describe the call site and never change const ELevel mLevel; const char* const mFile; - const int mLine; - const std::type_info& mClassInfo; + const int mLine; + const std::type_info& mClassInfo; const char* const mFunction; + const char* const mBroadTag; + const char* const mNarrowTag; + const bool mPrintOnce; // these implement a cache of the call to shouldLog() bool mCached; @@ -200,39 +203,66 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; See top of file for common usage. */ -#define lllog(level) \ +#define lllog(level, broadTag, narrowTag, once) \ { \ static LLError::CallSite _site( \ - level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__);\ + level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\ if (_site.shouldLog()) \ { \ std::ostringstream* _out = LLError::Log::out(); \ (*_out) - + +// DEPRECATED: Don't call directly, use LL_ENDL instead, which actually looks like a macro #define llendl \ LLError::End(); \ LLError::Log::flush(_out, _site); \ } \ } -#define llinfos lllog(LLError::LEVEL_INFO) -#define lldebugs lllog(LLError::LEVEL_DEBUG) -#define llwarns lllog(LLError::LEVEL_WARN) -#define llerrs lllog(LLError::LEVEL_ERROR) - +// DEPRECATED: Use the new macros that allow tags and *look* like macros. +#define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false) +#define llinfos lllog(LLError::LEVEL_INFO, NULL, NULL, false) +#define llwarns lllog(LLError::LEVEL_WARN, NULL, NULL, false) +#define llerrs lllog(LLError::LEVEL_ERROR, NULL, NULL, false) #define llcont (*_out) + +// NEW Macros for debugging, allow the passing of a string tag + +// One Tag +#define LL_DEBUGS(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, false) +#define LL_INFOS(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, false) +#define LL_WARNS(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, false) +#define LL_ERRS(broadTag) lllog(LLError::LEVEL_ERROR, broadTag, NULL, false) +// Two Tags +#define LL_DEBUGS2(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, false) +#define LL_INFOS2(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, false) +#define LL_WARNS2(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, false) +#define LL_ERRS2(broadTag, narrowTag) lllog(LLError::LEVEL_ERROR, broadTag, narrowTag, false) + +// Only print the log message once (good for warnings or infos that would otherwise +// spam the log file over and over, such as tighter loops). +#define LL_DEBUGS_ONCE(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, true) +#define LL_INFOS_ONCE(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, true) +#define LL_WARNS_ONCE(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, true) +#define LL_DEBUGS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, true) +#define LL_INFOS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, true) +#define LL_WARNS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, true) + +#define LL_ENDL llendl +#define LL_CONT (*_out) + /* Use this construct if you need to do computation in the middle of a message: - llinfos << "the agent " << agend_id; + LL_INFOS("AgentGesture") << "the agent " << agend_id; switch (f) { - case FOP_SHRUGS: llcont << "shrugs"; break; - case FOP_TAPS: llcont << "points at " << who; break; - case FOP_SAYS: llcont << "says " << message; break; + case FOP_SHRUGS: LL_CONT << "shrugs"; break; + case FOP_TAPS: LL_CONT << "points at " << who; break; + case FOP_SAYS: LL_CONT << "says " << message; break; } - llcont << " for " << t << " seconds" << llendl; + LL_CONT << " for " << t << " seconds" << LL_ENDL; Such computation is done iff the message will be logged. */ diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index cf984e4fe2..af89a09d2f 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -334,7 +334,7 @@ void LLTimer::setTimerExpirySec(F32 expiration) + (U64)((F32)(expiration * gClockFrequency)); } -F32 LLTimer::getRemainingTimeF32() +F32 LLTimer::getRemainingTimeF32() const { U64 cur_ticks = get_clock_count(); if (cur_ticks > mExpirationTicks) @@ -359,7 +359,7 @@ BOOL LLTimer::checkExpirationAndReset(F32 expiration) } -BOOL LLTimer::hasExpired() +BOOL LLTimer::hasExpired() const { return (get_clock_count() >= mExpirationTicks) ? TRUE : FALSE; @@ -561,3 +561,4 @@ void LLEventTimer::updateClass() } } + diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 113eb1e9e3..57f9e23e7a 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -87,11 +87,11 @@ public: void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time void setTimerExpirySec(F32 expiration); BOOL checkExpirationAndReset(F32 expiration); - BOOL hasExpired(); + BOOL hasExpired() const; F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset F64 getElapsedTimeAndResetF64(); - F32 getRemainingTimeF32(); + F32 getRemainingTimeF32() const; static BOOL knownBadTimer(); |