diff options
author | Richard Linden <none@none> | 2013-08-12 20:05:16 -0700 |
---|---|---|
committer | Richard Linden <none@none> | 2013-08-12 20:05:16 -0700 |
commit | cc31b4ae7934010762b8aaaa7e190c74a1cd7820 (patch) | |
tree | 61bb7e622417a5223fa108522e16f6b7dee147f3 /indra/llcommon | |
parent | e340009fc59d59e59b2e8d903a884acb76b178eb (diff) |
SH-4399 FIX: Interesting: Texture console MB Bound 0/384 and texture queue bounces once per second
SH-4346 FIX: Interesting: some integer Statistics are displayed as floating point after crossing region boundary
made llerrs/infos/etc properly variadic wrt tags
LL_INFOS("A", "B", "C") works, for example
fixed unit tests
remove llsimplestat
Diffstat (limited to 'indra/llcommon')
-rwxr-xr-x | indra/llcommon/llerror.cpp | 507 | ||||
-rwxr-xr-x | indra/llcommon/llerror.h | 79 | ||||
-rwxr-xr-x | indra/llcommon/llerrorcontrol.h | 20 | ||||
-rw-r--r-- | indra/llcommon/lltrace.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 10 | ||||
-rw-r--r-- | indra/llcommon/lltraceaccumulators.h | 12 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 150 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 87 | ||||
-rw-r--r-- | indra/llcommon/llunit.h | 64 | ||||
-rwxr-xr-x | indra/llcommon/tests/commonmisc_test.cpp | 10 | ||||
-rwxr-xr-x | indra/llcommon/tests/llerror_test.cpp | 90 | ||||
-rwxr-xr-x | indra/llcommon/tests/llsdserialize_test.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/tests/llunits_test.cpp | 6 |
13 files changed, 557 insertions, 482 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 652d0e212a..6f128d0a20 100755 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -51,7 +51,26 @@ #include "lltimer.h" namespace { -#if !LL_WINDOWS +#if LL_WINDOWS + void debugger_print(const std::string& s) + { + // Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C + // which works just fine under the windows debugger, but can cause users who + // have enabled SEHOP exception chain validation to crash due to interactions + // between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707 + // + if (IsDebuggerPresent()) + { + // Need UTF16 for Unicode OutputDebugString + // + if (s.size()) + { + OutputDebugString(utf8str_to_utf16str(s).c_str()); + OutputDebugString(TEXT("\n")); + } + } + } +#else class RecordToSyslog : public LLError::Recorder { public: @@ -98,6 +117,7 @@ namespace { { LL_INFOS() << "Error setting log file to " << filename << LL_ENDL; } + mWantsTime = true; } ~RecordToFile() @@ -107,8 +127,6 @@ namespace { bool okay() { return mFile; } - virtual bool wantsTime() { return true; } - virtual void recordMessage(LLError::ELevel level, const std::string& message) { @@ -123,10 +141,11 @@ namespace { class RecordToStderr : public LLError::Recorder { public: - RecordToStderr(bool timestamp) : mTimestamp(timestamp), mUseANSI(ANSI_PROBE) { } + RecordToStderr(bool timestamp) : mUseANSI(ANSI_PROBE) + { + mWantsTime = timestamp; + } - virtual bool wantsTime() { return mTimestamp; } - virtual void recordMessage(LLError::ELevel level, const std::string& message) { @@ -156,7 +175,6 @@ namespace { } private: - bool mTimestamp; enum ANSIState { ANSI_PROBE, @@ -202,10 +220,13 @@ namespace { class RecordToWinDebug: public LLError::Recorder { public: + RecordToWinDebug() + {} + virtual void recordMessage(LLError::ELevel level, const std::string& message) { - LL_WINDOWS_OUTPUT_DEBUG(message); + debugger_print(message); } }; #endif @@ -217,7 +238,7 @@ namespace std::string className(const std::type_info& type) { #ifdef __GNUC__ - // GCC: type_info::name() returns a mangled class name, must demangle + // GCC: type_info::name() returns a mangled class name,st demangle static size_t abi_name_len = 100; static char* abi_name_buf = (char*)malloc(abi_name_len); @@ -394,25 +415,25 @@ namespace LLError class Settings { public: - bool printLocation; + bool mPrintLocation; - LLError::ELevel defaultLevel; - - LevelMap functionLevelMap; - LevelMap classLevelMap; - LevelMap fileLevelMap; - LevelMap tagLevelMap; - std::map<std::string, unsigned int> uniqueLogMessages; - - LLError::FatalFunction crashFunction; - LLError::TimeFunction timeFunction; - - Recorders recorders; - Recorder* fileRecorder; - Recorder* fixedBufferRecorder; - std::string fileRecorderFileName; - - int shouldLogCallCounter; + LLError::ELevel mDefaultLevel; + + LevelMap mFunctionLevelMap; + LevelMap mClassLevelMap; + LevelMap mFileLevelMap; + LevelMap mTagLevelMap; + std::map<std::string, unsigned int> mUniqueLogMessages; + + LLError::FatalFunction mCrashFunction; + LLError::TimeFunction mTimeFunction; + + Recorders mRecorders; + Recorder* mFileRecorder; + Recorder* mFixedBufferRecorder; + std::string mFileRecorderFileName; + + int mShouldLogCallCounter; static Settings& get(); @@ -422,18 +443,18 @@ namespace LLError private: Settings() - : printLocation(false), - defaultLevel(LLError::LEVEL_DEBUG), - crashFunction(), - timeFunction(NULL), - fileRecorder(NULL), - fixedBufferRecorder(NULL), - shouldLogCallCounter(0) - { } + : mPrintLocation(false), + mDefaultLevel(LLError::LEVEL_DEBUG), + mCrashFunction(), + mTimeFunction(NULL), + mFileRecorder(NULL), + mFixedBufferRecorder(NULL), + mShouldLogCallCounter(NULL) + {} ~Settings() { - for_each(recorders.begin(), recorders.end(), + for_each(mRecorders.begin(), mRecorders.end(), DeletePointer()); } @@ -494,8 +515,8 @@ namespace LLError const std::type_info& class_info, const char* function, bool printOnce, - const char* broadTag, - const char* narrowTag) + const char** tags, + size_t tag_count) : mLevel(level), mFile(file), mLine(line), @@ -504,37 +525,53 @@ namespace LLError mCached(false), mShouldLog(false), mPrintOnce(printOnce), - mBroadTag(broadTag), - mNarrowTag(narrowTag) - {} - - CallSite::CallSite(ELevel level, - const char* file, - int line, - const std::type_info& class_info, - const char* function, - bool printOnce, - const char* broadTag, - const char* narrowTag, - const char*, - ...) - : mLevel(level), - mFile(file), - mLine(line), - mClassInfo(class_info), - mFunction(function), - mCached(false), - mShouldLog(false), - mPrintOnce(printOnce), - mBroadTag(broadTag), - mNarrowTag(narrowTag) + mTags(new const char* [tag_count]), + mTagCount(tag_count) { - LL_ERRS() << "No support for more than 2 logging tags" << LL_ENDL; + for (int i = 0; i < tag_count; i++) + { + mTags[i] = tags[i]; + } + + switch (mLevel) + { + case LEVEL_DEBUG: mLevelString = "DEBUG:"; break; + case LEVEL_INFO: mLevelString = "INFO:"; break; + case LEVEL_WARN: mLevelString = "WARNING:"; break; + case LEVEL_ERROR: mLevelString = "ERROR:"; break; + default: mLevelString = "XXX:"; break; + }; + + mLocationString = llformat("%s(%d) :", abbreviateFile(mFile).c_str(), mLine); +#if LL_WINDOWS + // DevStudio: __FUNCTION__ already includes the full class name +#else +#if LL_LINUX + // gross, but typeid comparison seems to always fail here with gcc4.1 + if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name())) +#else + if (site.mClassInfo != typeid(NoClassInfo)) +#endif // LL_LINUX + { + mFunctionString = className(site.mClassInfo) + "::"; + } +#endif + mFunctionString += std::string(mFunction) + ":"; + for (size_t i = 0; i < mTagCount; i++) + { + mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : " "); + } } + CallSite::~CallSite() + { + delete []mTags; + } void CallSite::invalidate() - { mCached = false; } + { + mCached = false; + } } namespace @@ -620,25 +657,25 @@ namespace LLError void setPrintLocation(bool print) { Settings& s = Settings::get(); - s.printLocation = print; + s.mPrintLocation = print; } void setFatalFunction(const FatalFunction& f) { Settings& s = Settings::get(); - s.crashFunction = f; + s.mCrashFunction = f; } FatalFunction getFatalFunction() { Settings& s = Settings::get(); - return s.crashFunction; + return s.mCrashFunction; } void setTimeFunction(TimeFunction f) { Settings& s = Settings::get(); - s.timeFunction = f; + s.mTimeFunction = f; } void setDefaultLevel(ELevel level) @@ -646,13 +683,13 @@ namespace LLError Globals& g = Globals::get(); Settings& s = Settings::get(); g.invalidateCallSites(); - s.defaultLevel = level; + s.mDefaultLevel = level; } ELevel getDefaultLevel() { Settings& s = Settings::get(); - return s.defaultLevel; + return s.mDefaultLevel; } void setFunctionLevel(const std::string& function_name, ELevel level) @@ -660,7 +697,7 @@ namespace LLError Globals& g = Globals::get(); Settings& s = Settings::get(); g.invalidateCallSites(); - s.functionLevelMap[function_name] = level; + s.mFunctionLevelMap[function_name] = level; } void setClassLevel(const std::string& class_name, ELevel level) @@ -668,7 +705,7 @@ namespace LLError Globals& g = Globals::get(); Settings& s = Settings::get(); g.invalidateCallSites(); - s.classLevelMap[class_name] = level; + s.mClassLevelMap[class_name] = level; } void setFileLevel(const std::string& file_name, ELevel level) @@ -676,7 +713,7 @@ namespace LLError Globals& g = Globals::get(); Settings& s = Settings::get(); g.invalidateCallSites(); - s.fileLevelMap[file_name] = level; + s.mFileLevelMap[file_name] = level; } void setTagLevel(const std::string& tag_name, ELevel level) @@ -684,7 +721,7 @@ namespace LLError Globals& g = Globals::get(); Settings& s = Settings::get(); g.invalidateCallSites(); - s.tagLevelMap[tag_name] = level; + s.mTagLevelMap[tag_name] = level; } LLError::ELevel decodeLevel(std::string name) @@ -732,11 +769,11 @@ namespace LLError Settings& s = Settings::get(); g.invalidateCallSites(); - s.functionLevelMap.clear(); - s.classLevelMap.clear(); - s.fileLevelMap.clear(); - s.tagLevelMap.clear(); - s.uniqueLogMessages.clear(); + s.mFunctionLevelMap.clear(); + s.mClassLevelMap.clear(); + s.mFileLevelMap.clear(); + s.mTagLevelMap.clear(); + s.mUniqueLogMessages.clear(); setPrintLocation(config["print-location"]); setDefaultLevel(decodeLevel(config["default-level"])); @@ -749,10 +786,10 @@ namespace LLError ELevel level = decodeLevel(entry["level"]); - setLevels(s.functionLevelMap, entry["functions"], level); - setLevels(s.classLevelMap, entry["classes"], level); - setLevels(s.fileLevelMap, entry["files"], level); - setLevels(s.tagLevelMap, entry["tags"], level); + setLevels(s.mFunctionLevelMap, entry["functions"], level); + setLevels(s.mClassLevelMap, entry["classes"], level); + setLevels(s.mFileLevelMap, entry["files"], level); + setLevels(s.mTagLevelMap, entry["tags"], level); } } } @@ -760,19 +797,44 @@ namespace LLError namespace LLError { + Recorder::Recorder() + : mWantsTime(false), + mWantsTags(false), + mWantsLevel(true), + mWantsLocation(false), + mWantsFunctionName(true) + {} + Recorder::~Recorder() {} - // virtual bool Recorder::wantsTime() { - return false; + return mWantsTime; } // virtual bool Recorder::wantsTags() { - return false; + return mWantsTags; + } + + // virtual + bool Recorder::wantsLevel() + { + return mWantsLevel; + } + + // virtual + bool Recorder::wantsLocation() + { + return mWantsLocation; + } + + // virtual + bool Recorder::wantsFunctionName() + { + return mWantsFunctionName; } void addRecorder(Recorder* recorder) @@ -782,7 +844,7 @@ namespace LLError return; } Settings& s = Settings::get(); - s.recorders.push_back(recorder); + s.mRecorders.push_back(recorder); } void removeRecorder(Recorder* recorder) @@ -792,8 +854,8 @@ namespace LLError return; } Settings& s = Settings::get(); - s.recorders.erase(std::remove(s.recorders.begin(), s.recorders.end(), recorder), - s.recorders.end()); + s.mRecorders.erase(std::remove(s.mRecorders.begin(), s.mRecorders.end(), recorder), + s.mRecorders.end()); } } @@ -803,10 +865,10 @@ namespace LLError { LLError::Settings& s = LLError::Settings::get(); - removeRecorder(s.fileRecorder); - delete s.fileRecorder; - s.fileRecorder = NULL; - s.fileRecorderFileName.clear(); + removeRecorder(s.mFileRecorder); + delete s.mFileRecorder; + s.mFileRecorder = NULL; + s.mFileRecorderFileName.clear(); if (file_name.empty()) { @@ -820,8 +882,8 @@ namespace LLError return; } - s.fileRecorderFileName = file_name; - s.fileRecorder = f; + s.mFileRecorderFileName = file_name; + s.mFileRecorder = f; addRecorder(f); } @@ -829,132 +891,114 @@ namespace LLError { LLError::Settings& s = LLError::Settings::get(); - removeRecorder(s.fixedBufferRecorder); - delete s.fixedBufferRecorder; - s.fixedBufferRecorder = NULL; + removeRecorder(s.mFixedBufferRecorder); + delete s.mFixedBufferRecorder; + s.mFixedBufferRecorder = NULL; if (!fixedBuffer) { return; } - s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer); - addRecorder(s.fixedBufferRecorder); + s.mFixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer); + addRecorder(s.mFixedBufferRecorder); } std::string logFileName() { LLError::Settings& s = LLError::Settings::get(); - return s.fileRecorderFileName; + return s.mFileRecorderFileName; } } namespace { - void writeToRecorders(const LLError::CallSite& site, const std::string& message) + void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true) { LLError::ELevel level = site.mLevel; LLError::Settings& s = LLError::Settings::get(); - std::string messageWithTime; - std::string messageWithTags; - std::string messageWithTagsAndTime; - - for (Recorders::const_iterator i = s.recorders.begin(); - i != s.recorders.end(); + for (Recorders::const_iterator i = s.mRecorders.begin(); + i != s.mRecorders.end(); ++i) { LLError::Recorder* r = *i; - - if (r->wantsTime() && s.timeFunction != NULL) - { - if (r->wantsTags()) - { - if (messageWithTagsAndTime.empty()) - { - messageWithTagsAndTime = s.timeFunction() + " " - + (site.mBroadTag ? (std::string("#") + std::string(site.mBroadTag) + " ") : std::string()) - + (site.mNarrowTag ? (std::string("#") + std::string(site.mNarrowTag) + " ") : std::string()) - + message; - } - - r->recordMessage(level, messageWithTagsAndTime); - } - else - { - if (messageWithTime.empty()) - { - messageWithTime = s.timeFunction() + " " + message; - } - r->recordMessage(level, messageWithTime); - } - } - else + std::ostringstream message_stream; + + if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation)) { - if (r->wantsTags()) - { - if (messageWithTags.empty()) - { - messageWithTags = (site.mBroadTag ? (std::string("#") + std::string(site.mBroadTag) + " ") : std::string()) - + (site.mNarrowTag ? (std::string("#") + std::string(site.mNarrowTag) + " ") : std::string()) - + message; - } - - r->recordMessage(level, messageWithTags); - } - else - { - r->recordMessage(level, message); - } + message_stream << site.mLocationString << " "; } - } - } -} - -/* -Recorder formats: + if (show_time && r->wantsTime() && s.mTimeFunction != NULL) + { + message_stream << s.mTimeFunction() << " "; + } -$type = "ERROR" | "WARNING" | "ALERT" | "INFO" | "DEBUG" -$loc = "$file($line)" -$msg = "$loc : " if FATAL or printing loc - "" otherwise -$msg += "$type: " -$msg += contents of stringstream + if (show_tags && r->wantsTags()) + { + message_stream << site.mTagString << " "; + } -$time = "%Y-%m-%dT%H:%M:%SZ" if UTC - or "%Y-%m-%dT%H:%M:%S %Z" if local + if (show_level && r->wantsLevel()) + { + message_stream << site.mLevelString << " "; + } + + if (show_function && r->wantsFunctionName()) + { + message_stream << site.mFunctionString << " "; + } -syslog: "$msg" -file: "$time $msg\n" -stderr: "$time $msg\n" except on windows, "$msg\n" -fixedbuf: "$msg" -winddebug: "$msg\n" + message_stream << message; -Note: if FATAL, an additional line gets logged first, with $msg set to - "$loc : error" - -You get: - llfoo.cpp(42) : error - llfoo.cpp(42) : ERROR: something - -*/ + r->recordMessage(level, message_stream.str()); + } + } +} namespace { bool checkLevelMap(const LevelMap& map, const std::string& key, LLError::ELevel& level) { + bool stop_checking; LevelMap::const_iterator i = map.find(key); if (i == map.end()) { - return false; + return stop_checking = false; } - level = i->second; - return true; + level = i->second; + return stop_checking = true; } + bool checkLevelMap( const LevelMap& map, + const char *const * keys, + size_t count, + LLError::ELevel& level) + { + bool found_level = false; + + LLError::ELevel tag_level = LLError::LEVEL_NONE; + + for (size_t i = 0; i < count; i++) + { + LevelMap::const_iterator it = map.find(keys[i]); + if (it != map.end()) + { + found_level = true; + tag_level = llmin(tag_level, it->second); + } + } + + if (found_level) + { + level = tag_level; + } + return found_level; + } + class LogLock { public: @@ -1019,10 +1063,10 @@ namespace LLError Globals& g = Globals::get(); Settings& s = Settings::get(); - s.shouldLogCallCounter += 1; - - std::string class_name = className(site.mClassInfo); - std::string function_name = functionName(site.mFunction); + s.mShouldLogCallCounter++; + + std::string& class_name = className(site.mClassInfo); + std::string& function_name = functionName(site.mFunction); #if LL_LINUX // gross, but typeid comparison seems to always fail here with gcc4.1 if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name())) @@ -1033,17 +1077,18 @@ namespace LLError function_name = class_name + "::" + function_name; } - ELevel compareLevel = s.defaultLevel; + ELevel compareLevel = s.mDefaultLevel; // 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) - || ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false); + // Default < Tags < File < Class < Function + checkLevelMap(s.mFunctionLevelMap, function_name, compareLevel) + || checkLevelMap(s.mClassLevelMap, class_name, compareLevel) + || checkLevelMap(s.mFileLevelMap, abbreviateFile(site.mFile), compareLevel) + || (site.mTagCount > 0 + ? checkLevelMap(s.mTagLevelMap, site.mTags, site.mTagCount, compareLevel) + : false); site.mCached = true; g.addCallSite(site); @@ -1126,56 +1171,21 @@ namespace LLError if (site.mLevel == LEVEL_ERROR) { - std::ostringstream fatalMessage; - fatalMessage << abbreviateFile(site.mFile) - << "(" << site.mLine << ") : error"; - - writeToRecorders(site, fatalMessage.str()); + writeToRecorders(site, "error", true, true, true, false, false); } + std::ostringstream message_stream; - std::ostringstream prefix; - - switch (site.mLevel) - { - case LEVEL_DEBUG: prefix << "DEBUG: "; break; - case LEVEL_INFO: prefix << "INFO: "; break; - case LEVEL_WARN: prefix << "WARNING: "; break; - case LEVEL_ERROR: prefix << "ERROR: "; break; - default: prefix << "XXX: "; break; - }; - - if (s.printLocation) - { - prefix << abbreviateFile(site.mFile) - << "(" << site.mLine << ") : "; - } - - #if LL_WINDOWS - // DevStudio: __FUNCTION__ already includes the full class name - #else - #if LL_LINUX - // gross, but typeid comparison seems to always fail here with gcc4.1 - if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name())) - #else - if (site.mClassInfo != typeid(NoClassInfo)) - #endif // LL_LINUX - { - prefix << className(site.mClassInfo) << "::"; - } - #endif - prefix << site.mFunction << ": "; - if (site.mPrintOnce) { - std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message); - if (messageIter != s.uniqueLogMessages.end()) + std::map<std::string, unsigned int>::iterator messageIter = s.mUniqueLogMessages.find(message); + if (messageIter != s.mUniqueLogMessages.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): "; + message_stream << "ONCE (" << num_messages << "th time seen): "; } else { @@ -1184,26 +1194,22 @@ namespace LLError } else { - prefix << "ONCE: "; - s.uniqueLogMessages[message] = 1; + message_stream << "ONCE: "; + s.mUniqueLogMessages[message] = 1; } } - prefix << message; - message = prefix.str(); + message_stream << message; - writeToRecorders(site, message); + writeToRecorders(site, message_stream.str()); - if (site.mLevel == LEVEL_ERROR && s.crashFunction) + if (site.mLevel == LEVEL_ERROR && s.mCrashFunction) { - s.crashFunction(message); + s.mCrashFunction(message_stream.str()); } } } - - - namespace LLError { Settings* saveAndResetSettings() @@ -1260,7 +1266,7 @@ namespace LLError int shouldLogCallCount() { Settings& s = Settings::get(); - return s.shouldLogCallCounter; + return s.mShouldLogCallCounter; } #if LL_WINDOWS @@ -1471,26 +1477,5 @@ namespace LLError sIndex = 0; } -#if LL_WINDOWS - void LLOutputDebugUTF8(const std::string& s) - { - // Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C - // which works just fine under the windows debugger, but can cause users who - // have enabled SEHOP exception chain validation to crash due to interactions - // between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707 - // - if (IsDebuggerPresent()) - { - // Need UTF16 for Unicode OutputDebugString - // - if (s.size()) - { - OutputDebugString(utf8str_to_utf16str(s).c_str()); - OutputDebugString(TEXT("\n")); - } - } - } -#endif - } diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index ef25a0173c..7810676388 100755 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -194,14 +194,26 @@ namespace LLError // Represents a specific place in the code where a message is logged // This is public because it is used by the macros below. It is not // intended for public use. - CallSite(ELevel, const char* file, int line, - const std::type_info& class_info, const char* function, bool printOnce, const char* broadTag = NULL, const char* narrowTag = NULL ); + CallSite(ELevel level, + const char* file, + int line, + const std::type_info& class_info, + const char* function, + bool print_once, + const char** tags, + size_t tag_count); + + ~CallSite(); #ifdef LL_LIBRARY_INCLUDE bool shouldLog(); #else // LL_LIBRARY_INCLUDE bool shouldLog() - { return mCached ? mShouldLog : Log::shouldLog(*this); } + { + return mCached + ? mShouldLog + : Log::shouldLog(*this); + } // this member function needs to be in-line for efficiency #endif // LL_LIBRARY_INCLUDE @@ -213,20 +225,17 @@ namespace LLError const int mLine; const std::type_info& mClassInfo; const char* const mFunction; - const char* const mBroadTag; - const char* const mNarrowTag; + const char** mTags; + size_t mTagCount; const bool mPrintOnce; - - // these implement a cache of the call to shouldLog() - bool mCached; - bool mShouldLog; + const char* mLevelString; + std::string mLocationString, + mFunctionString, + mTagString; + bool mCached, + mShouldLog; friend class Log; - - private: - // 3 or more tags not currently supported - CallSite(ELevel, const char* file, int line, - const std::type_info& class_info, const char* function, bool printOnce, const char* broadTag, const char* narrowTag, const char*, ...); }; @@ -258,30 +267,21 @@ namespace LLError static void clear() ; static void end(std::ostringstream* _out) ; }; - -#if LL_WINDOWS - void LLOutputDebugUTF8(const std::string& s); -#endif - } -#if LL_WINDOWS - // Macro accepting a std::string for display in windows debugging console - #define LL_WINDOWS_OUTPUT_DEBUG(a) LLError::LLOutputDebugUTF8(a) -#else - #define LL_WINDOWS_OUTPUT_DEBUG(a) -#endif - //this is cheaper than llcallstacks if no need to output other variables to call stacks. #define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__) -#define llcallstacks \ - {\ + +#define llcallstacks \ + { \ std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; \ (*_out) -#define llcallstacksendl \ - LLError::End(); \ + +#define llcallstacksendl \ + LLError::End(); \ LLError::LLCallStacks::end(_out) ; \ } + #define LL_CLEAR_CALLSTACKS() LLError::LLCallStacks::clear() #define LL_PRINT_CALLSTACKS() LLError::LLCallStacks::print() @@ -302,13 +302,18 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; // See top of file for common usage. ///////////////////////////////// -#define lllog(level, once, ...) \ - do { \ - static LLError::CallSite _site( \ - level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, ##__VA_ARGS__ );\ - if (LL_UNLIKELY(_site.shouldLog())) \ - { \ - std::ostringstream* _out = LLError::Log::out(); \ +// this macro uses a one-shot do statement to avoid parsing errors when writing: +// if (condition) LL_INFOS() << "True" << LLENDL; else LLINFOS() << "False" << LLENDL + +#define lllog(level, once, ...) \ + do { \ + const char* tags[] = {"", ##__VA_ARGS__}; \ + size_t tag_count = LL_ARRAY_SIZE(tags) - 1; \ + static LLError::CallSite _site( \ + level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\ + if (LL_UNLIKELY(_site.shouldLog())) \ + { \ + std::ostringstream* _out = LLError::Log::out(); \ (*_out) //Use this construct if you need to do computation in the middle of a diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 7c9df57115..aab695094c 100755 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -136,18 +136,24 @@ namespace LLError { // An object that handles the actual output or error messages. public: + Recorder(); virtual ~Recorder(); virtual void recordMessage(LLError::ELevel, const std::string& message) = 0; // use the level for better display, not for filtering - virtual bool wantsTime(); // default returns false - // override and return true if the recorder wants the time string - // included in the text of the message - - virtual bool wantsTags(); // default returns false - // override ands return true if the recorder wants the tags included - // in the text of the message + bool wantsTime(); + bool wantsTags(); + bool wantsLevel(); + bool wantsLocation(); + bool wantsFunctionName(); + + protected: + bool mWantsTime, + mWantsTags, + mWantsLevel, + mWantsLocation, + mWantsFunctionName; }; /** diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp index eedf1b06f1..436ad9a0a2 100644 --- a/indra/llcommon/lltrace.cpp +++ b/indra/llcommon/lltrace.cpp @@ -45,7 +45,7 @@ TraceBase::TraceBase( const char* name, const char* description ) #endif } -const char* TraceBase::getUnitLabel() +const char* TraceBase::getUnitLabel() const { return ""; } diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index 75e913a348..1f86aadaba 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -58,7 +58,7 @@ class TraceBase public: TraceBase(const char* name, const char* description); virtual ~TraceBase() {}; - virtual const char* getUnitLabel(); + virtual const char* getUnitLabel() const; const std::string& getName() const { return mName; } const std::string& getDescription() const { return mDescription; } @@ -129,7 +129,7 @@ public: : trace_t(name, description) {} - /*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); } + /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); } }; @@ -153,7 +153,7 @@ public: : trace_t(name, description) {} - /*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); } + /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); } }; template<typename T, typename VALUE_T> @@ -176,7 +176,7 @@ public: : trace_t(name, description) {} - /*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); } + /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); } }; template<typename T, typename VALUE_T> @@ -227,7 +227,7 @@ public: : trace_t(name) {} - /*virtual*/ const char* getUnitLabel() { return "B"; } + /*virtual*/ const char* getUnitLabel() const { return "B"; } TraceType<MemStatAccumulator::AllocationCountFacet>& allocationCount() { diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h index 5871dc4bea..ef73bd3091 100644 --- a/indra/llcommon/lltraceaccumulators.h +++ b/indra/llcommon/lltraceaccumulators.h @@ -223,7 +223,6 @@ namespace LLTrace { public: typedef F64 value_t; - typedef F64 mean_t; EventAccumulator() : mSum(NaN), @@ -269,6 +268,7 @@ namespace LLTrace F64 getLastValue() const { return mLastValue; } F64 getMean() const { return mMean; } F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); } + F64 getSumOfSquares() const { return mSumOfSquares; } U32 getSampleCount() const { return mNumSamples; } bool hasValue() const { return mNumSamples > 0; } @@ -289,7 +289,6 @@ namespace LLTrace { public: typedef F64 value_t; - typedef F64 mean_t; SampleAccumulator() : mSum(0), @@ -353,6 +352,8 @@ namespace LLTrace F64 getLastValue() const { return mLastValue; } F64 getMean() const { return mMean; } F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); } + F64 getSumOfSquares() const { return mSumOfSquares; } + LLUnitImplicit<F64, LLUnits::Seconds> getSamplingTime() { return mTotalSamplingTime; } U32 getSampleCount() const { return mNumSamples; } bool hasValue() const { return mHasValue; } @@ -378,7 +379,6 @@ namespace LLTrace { public: typedef F64 value_t; - typedef F64 mean_t; CountAccumulator() : mSum(0), @@ -419,20 +419,17 @@ namespace LLTrace { public: typedef LLUnit<F64, LLUnits::Seconds> value_t; - typedef LLUnit<F64, LLUnits::Seconds> mean_t; typedef TimeBlockAccumulator self_t; // fake classes that allows us to view different facets of underlying statistic struct CallCountFacet { typedef U32 value_t; - typedef F32 mean_t; }; struct SelfTimeFacet { typedef LLUnit<F64, LLUnits::Seconds> value_t; - typedef LLUnit<F64, LLUnits::Seconds> mean_t; }; TimeBlockAccumulator(); @@ -486,19 +483,16 @@ namespace LLTrace struct AllocationCountFacet { typedef U32 value_t; - typedef F32 mean_t; }; struct DeallocationCountFacet { typedef U32 value_t; - typedef F32 mean_t; }; struct ChildMemFacet { typedef LLUnit<F64, LLUnits::Bytes> value_t; - typedef LLUnit<F64, LLUnits::Bytes> mean_t; }; MemStatAccumulator() diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index a4d58d8ab1..42d97ce314 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -242,9 +242,7 @@ F64 Recording::getSum( const TraceType<EventAccumulator>& stat ) F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat ) { F64 sum = mBuffers->mCounts[stat.getIndex()].getSum(); - return (sum != 0.0) - ? (sum / mElapsedSeconds.value()) - : 0.0; + return sum / mElapsedSeconds.value(); } U32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat ) @@ -522,71 +520,98 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other) getCurRecording().splitTo(other.getCurRecording()); } - -F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) +F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - F64 mean = 0; - if (num_periods <= 0) { return mean; } - - S32 total_sample_count = 0; - + bool has_value = false; + F64 min_val = std::numeric_limits<F64>::max(); for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - Recording& recording = mRecordingPeriods[index]; - + Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) { - S32 period_sample_count = recording.getSampleCount(stat); - mean += recording.getMean(stat) * period_sample_count; - total_sample_count += period_sample_count; + min_val = llmin(min_val, recording.getMin(stat)); + has_value = true; } } - if (total_sample_count) + return has_value + ? min_val + : NaN; +} + +F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) +{ + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); + + bool has_value = false; + F64 max_val = std::numeric_limits<F64>::min(); + for (S32 i = 1; i <= num_periods; i++) { - mean = mean / total_sample_count; + Recording& recording = getPrevRecording(i); + if (recording.hasValue(stat)) + { + max_val = llmax(max_val, recording.getMax(stat)); + has_value = true; + } } - return mean; + + return has_value + ? max_val + : NaN; } -F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) +// calculates means using aggregates per period +F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - F64 min_val = std::numeric_limits<F64>::max(); + F64 mean = 0; + S32 valid_period_count = 0; + for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - Recording& recording = mRecordingPeriods[index]; + Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) { - min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat)); + mean += recording.getMean(stat); + valid_period_count++; } } - return min_val; + + return valid_period_count + ? mean / (F64)valid_period_count + : NaN; } -F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) + +F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) { size_t total_periods = mRecordingPeriods.size(); num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - F64 max_val = std::numeric_limits<F64>::min(); + F64 period_mean = getPeriodMean(stat, num_periods); + F64 sum_of_squares = 0; + S32 valid_period_count = 0; + for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - Recording& recording = mRecordingPeriods[index]; + Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) { - max_val = llmax(max_val, recording.getMax(stat)); + F64 delta = recording.getMean(stat) - period_mean; + sum_of_squares += delta * delta; + valid_period_count++; } } - return max_val; + + return valid_period_count + ? sqrt((F64)sum_of_squares / (F64)valid_period_count) + : NaN; } F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) @@ -594,17 +619,21 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, s size_t total_periods = mRecordingPeriods.size(); num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); + bool has_value = false; F64 min_val = std::numeric_limits<F64>::max(); for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - Recording& recording = mRecordingPeriods[index]; + Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) { min_val = llmin(min_val, recording.getMin(stat)); + has_value = true; } } - return min_val; + + return has_value + ? min_val + : NaN; } F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/) @@ -612,17 +641,21 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, si size_t total_periods = mRecordingPeriods.size(); num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); + bool has_value = false; F64 max_val = std::numeric_limits<F64>::min(); for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - Recording& recording = mRecordingPeriods[index]; + Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) { max_val = llmax(max_val, recording.getMax(stat)); + has_value = true; } } - return max_val; + + return has_value + ? max_val + : NaN; } @@ -631,31 +664,48 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat, size_t total_periods = mRecordingPeriods.size(); num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - LLUnit<F64, LLUnits::Seconds> total_duration(0.f); - + S32 valid_period_count = 0; F64 mean = 0; - if (num_periods <= 0) { return mean; } for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - Recording& recording = mRecordingPeriods[index]; + Recording& recording = getPrevRecording(i); if (recording.hasValue(stat)) { - LLUnit<F64, LLUnits::Seconds> recording_duration = recording.getDuration(); - mean += recording.getMean(stat) * recording_duration.value(); - total_duration += recording_duration; + mean += recording.getMean(stat); + valid_period_count++; } } - if (total_duration.value()) - { - mean = mean / total_duration; - } - return mean; + return valid_period_count + ? mean / F64(valid_period_count) + : NaN; } +F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) +{ + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); + F64 period_mean = getPeriodMean(stat, num_periods); + S32 valid_period_count = 0; + F64 sum_of_squares = 0; + + for (S32 i = 1; i <= num_periods; i++) + { + Recording& recording = getPrevRecording(i); + if (recording.hasValue(stat)) + { + F64 delta = recording.getMean(stat) - period_mean; + sum_of_squares += delta * delta; + valid_period_count++; + } + } + + return valid_period_count + ? sqrt(sum_of_squares / (F64)valid_period_count) + : NaN; +} /////////////////////////////////////////////////////////////////////// // ExtendableRecording diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 7ee8aba874..3722a61327 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -210,6 +210,7 @@ namespace LLTrace // SampleStatHandle accessors bool hasValue(const TraceType<SampleAccumulator>& stat); + F64 getMin(const TraceType<SampleAccumulator>& stat); template <typename T> T getMin(const SampleStatHandle<T>& stat) @@ -217,18 +218,18 @@ namespace LLTrace return (T)getMin(static_cast<const TraceType<SampleAccumulator>&> (stat)); } - F64 getMean(const TraceType<SampleAccumulator>& stat); + F64 getMax(const TraceType<SampleAccumulator>& stat); template <typename T> - typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat) + T getMax(const SampleStatHandle<T>& stat) { - return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat)); + return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat)); } - F64 getMax(const TraceType<SampleAccumulator>& stat); + F64 getMean(const TraceType<SampleAccumulator>& stat); template <typename T> - T getMax(const SampleStatHandle<T>& stat) + typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat) { - return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat)); + return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat)); } F64 getStandardDeviation(const TraceType<SampleAccumulator>& stat); @@ -345,8 +346,8 @@ namespace LLTrace size_t num_samples = 0; for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - num_samples += mRecordingPeriods[index].getSampleCount(stat); + Recording& recording = getPrevRecording(i); + num_samples += Recording.getSampleCount(stat); } return num_samples; } @@ -365,8 +366,8 @@ namespace LLTrace typename T::value_t min_val = std::numeric_limits<typename T::value_t>::max(); for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - min_val = llmin(min_val, mRecordingPeriods[index].getSum(stat)); + Recording& recording = getPrevRecording(i) + min_val = llmin(min_val, recording.getSum(stat)); } return min_val; } @@ -397,11 +398,11 @@ namespace LLTrace size_t total_periods = mNumPeriods; num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - F64 min_val = std::numeric_limits<F64>::max(); + RelatedTypes<typename T::value_t>::fractional_t min_val = std::numeric_limits<F64>::max(); for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - min_val = llmin(min_val, mRecordingPeriods[index].getPerSec(stat)); + Recording& recording = getPrevRecording(i); + min_val = llmin(min_val, recording.getPerSec(stat)); } return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val; } @@ -426,8 +427,8 @@ namespace LLTrace typename T::value_t max_val = std::numeric_limits<typename T::value_t>::min(); for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - max_val = llmax(max_val, mRecordingPeriods[index].getSum(stat)); + Recording& recording = getPrevRecording(i); + max_val = llmax(max_val, recording.getSum(stat)); } return max_val; } @@ -461,8 +462,8 @@ namespace LLTrace F64 max_val = std::numeric_limits<F64>::min(); for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - max_val = llmax(max_val, mRecordingPeriods[index].getPerSec(stat)); + Recording& recording = getPrevRecording(i); + max_val = llmax(max_val, recording.getPerSec(stat)); } return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val; } @@ -479,24 +480,24 @@ namespace LLTrace // catch all for stats that have a defined sum template <typename T> - typename T::mean_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX) + typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX) { size_t total_periods = mNumPeriods; num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - typename T::mean_t mean = 0; - if (num_periods <= 0) { return mean; } + typename RelatedTypes<T::value_t>::fractional_t mean = 0; for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - if (mRecordingPeriods[index].getDuration() > 0.f) + Recording& recording = getPrevRecording(i); + if (recording.getDuration() > 0.f) { - mean += mRecordingPeriods[index].getSum(stat); + mean += recording.getSum(stat); } } - mean = mean / num_periods; - return mean; + return RelatedTypes<T::value_t>::fractional_t(num_periods + ? mean / num_periods + : NaN); } template<typename T> @@ -519,24 +520,25 @@ namespace LLTrace } template <typename T> - typename RelatedTypes<typename T::mean_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) + typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) { size_t total_periods = mNumPeriods; num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods); - typename T::mean_t mean = 0; - if (num_periods <= 0) { return mean; } + typename RelatedTypes<T::value_t>::fractional_t mean = 0; for (S32 i = 1; i <= num_periods; i++) { - S32 index = (mCurPeriod + total_periods - i) % total_periods; - if (mRecordingPeriods[index].getDuration() > 0.f) + Recording& recording = getPrevRecording(i); + if (recording.getDuration() > 0.f) { - mean += mRecordingPeriods[index].getPerSec(stat); + mean += recording.getPerSec(stat); } } - mean = mean / num_periods; - return (typename RelatedTypes<typename T::mean_t>::fractional_t)mean; + + return RelatedTypes<T::value_t>::fractional_t(num_periods + ? mean / num_periods + : NaN); } template<typename T> @@ -545,6 +547,25 @@ namespace LLTrace return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods)); } + // + // PERIODIC STANDARD DEVIATION + // + + F64 getPeriodStandardDeviation(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX); + + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX) + { + return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodStandardDeviation(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX); + template<typename T> + typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX) + { + return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods)); + } + private: // implementation for LLStopWatchControlsMixin /*virtual*/ void handleStart(); diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h index 2e4c0de28f..b135be48fa 100644 --- a/indra/llcommon/llunit.h +++ b/indra/llcommon/llunit.h @@ -517,71 +517,79 @@ struct LLGetUnitLabel<LLUnit<STORAGE_T, T> > static const char* getUnitLabel() { return T::getUnitLabel(); } }; -template<typename VALUE_TYPE> +#define LL_UNIT_PROMOTE_VALUE(output_type, value) ((true ? (output_type)(1) : (value/value)) * value) + +template<typename INPUT_TYPE, typename OUTPUT_TYPE> struct LLUnitLinearOps { - typedef LLUnitLinearOps<VALUE_TYPE> self_t; - LLUnitLinearOps(VALUE_TYPE val) : mResult (val) {} + typedef LLUnitLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t; + + LLUnitLinearOps(INPUT_TYPE val) + : mInput (val) + {} - operator VALUE_TYPE() const { return mResult; } - VALUE_TYPE mResult; + operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; } + INPUT_TYPE mInput; template<typename T> - self_t operator * (T other) + output_t operator * (T other) { - return mResult * other; + return mInput * other; } template<typename T> - self_t operator / (T other) + output_t operator / (T other) { - return mResult / other; + return LL_UNIT_PROMOTE_VALUE(OUTPUT_TYPE, mInput) / other; } template<typename T> - self_t operator + (T other) + output_t operator + (T other) { - return mResult + other; + return mInput + other; } template<typename T> - self_t operator - (T other) + output_t operator - (T other) { - return mResult - other; + return mInput - other; } }; -template<typename VALUE_TYPE> +template<typename INPUT_TYPE, typename OUTPUT_TYPE> struct LLUnitInverseLinearOps { - typedef LLUnitInverseLinearOps<VALUE_TYPE> self_t; + typedef LLUnitInverseLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t; + + LLUnitInverseLinearOps(INPUT_TYPE val) + : mInput(val) + {} - LLUnitInverseLinearOps(VALUE_TYPE val) : mResult (val) {} - operator VALUE_TYPE() const { return mResult; } - VALUE_TYPE mResult; + operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; } + INPUT_TYPE mInput; template<typename T> - self_t operator * (T other) + output_t operator * (T other) { - return mResult / other; + return LL_UNIT_PROMOTE_VALUE(OUTPUT_TYPE, mInput) / other; } template<typename T> - self_t operator / (T other) + output_t operator / (T other) { - return mResult * other; + return mInput * other; } template<typename T> - self_t operator + (T other) + output_t operator + (T other) { - return mResult - other; + return mInput - other; } template<typename T> - self_t operator - (T other) + output_t operator - (T other) { - return mResult + other; + return mInput + other; } }; @@ -613,13 +621,13 @@ struct unit_name template<typename S1, typename S2> \ void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \ { \ - out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation)); \ + out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1, S2>(in.value()) conversion_operation)); \ } \ \ template<typename S1, typename S2> \ void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \ { \ - out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation)); \ + out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1, S2>(in.value()) conversion_operation)); \ } // diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp index b115c153c1..4b3e07fa75 100755 --- a/indra/llcommon/tests/commonmisc_test.cpp +++ b/indra/llcommon/tests/commonmisc_test.cpp @@ -339,7 +339,7 @@ namespace tut /* if(actual != expected) { - llwarns << "iteration " << i << llendl; + LL_WARNS() << "iteration " << i << LL_ENDL; std::ostringstream e_str; std::string::iterator iter = expected.begin(); std::string::iterator end = expected.end(); @@ -349,8 +349,8 @@ namespace tut } e_str << std::endl; llsd_serialize_string(e_str, expected); - llwarns << "expected size: " << expected.size() << llendl; - llwarns << "expected: " << e_str.str() << llendl; + LL_WARNS() << "expected size: " << expected.size() << LL_ENDL; + LL_WARNS() << "expected: " << e_str.str() << LL_ENDL; std::ostringstream a_str; iter = actual.begin(); @@ -361,8 +361,8 @@ namespace tut } a_str << std::endl; llsd_serialize_string(a_str, actual); - llwarns << "actual size: " << actual.size() << llendl; - llwarns << "actual: " << a_str.str() << llendl; + LL_WARNS() << "actual size: " << actual.size() << LL_ENDL; + LL_WARNS() << "actual: " << a_str.str() << LL_ENDL; } */ ensure_equals("string value", actual, expected); diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 279a90e51b..b28c5ba4b3 100755 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -40,7 +40,7 @@ namespace { void test_that_error_h_includes_enough_things_to_compile_a_message() { - llinfos << "!" << llendl; + LL_INFOS() << "!" << LL_ENDL; } } @@ -55,7 +55,7 @@ namespace tut class TestRecorder : public LLError::Recorder { public: - TestRecorder() : mWantsTime(false) { } + TestRecorder() { mWantsTime = false; } ~TestRecorder() { LLError::removeRecorder(this); } void recordMessage(LLError::ELevel level, @@ -68,7 +68,6 @@ namespace tut void clearMessages() { mMessages.clear(); } void setWantsTime(bool t) { mWantsTime = t; } - bool wantsTime() { return mWantsTime; } std::string message(int n) { @@ -82,8 +81,6 @@ namespace tut private: typedef std::vector<std::string> MessageVector; MessageVector mMessages; - - bool mWantsTime; }; struct ErrorTestData @@ -144,8 +141,8 @@ namespace tut void ErrorTestObject::test<1>() // basic test of output { - llinfos << "test" << llendl; - llinfos << "bob" << llendl; + LL_INFOS() << "test" << LL_ENDL; + LL_INFOS() << "bob" << LL_ENDL; ensure_message_contains(0, "test"); ensure_message_contains(1, "bob"); @@ -156,11 +153,11 @@ namespace { void writeSome() { - lldebugs << "one" << llendl; - llinfos << "two" << llendl; - llwarns << "three" << llendl; - llerrs << "four" << llendl; - // fatal messages write out and addtional "error" message + LL_DEBUGS() << "one" << LL_ENDL; + LL_INFOS() << "two" << LL_ENDL; + LL_WARNS() << "three" << LL_ENDL; + // fatal messages write out an additional "error" message + LL_ERRS() << "four" << LL_ENDL; } }; @@ -259,19 +256,20 @@ namespace std::string writeReturningLocation() { - llinfos << "apple" << llendl; int this_line = __LINE__; + LL_INFOS() << "apple" << LL_ENDL; int this_line = __LINE__; return locationString(this_line); } - std::string writeReturningLocationAndFunction() + void writeReturningLocationAndFunction(std::string& location, std::string& function) { - llinfos << "apple" << llendl; int this_line = __LINE__; - return locationString(this_line) + __FUNCTION__; + LL_INFOS() << "apple" << LL_ENDL; int this_line = __LINE__; + location = locationString(this_line); + function = __FUNCTION__; } std::string errorReturningLocation() { - llerrs << "die" << llendl; int this_line = __LINE__; + LL_ERRS() << "die" << LL_ENDL; int this_line = __LINE__; return locationString(this_line); } } @@ -306,13 +304,13 @@ namespace tut std::string logFromGlobal(bool id) { - llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl; + LL_INFOS() << (id ? "logFromGlobal: " : "") << "hi" << LL_ENDL; return "logFromGlobal"; } static std::string logFromStatic(bool id) { - llinfos << (id ? "logFromStatic: " : "") << "hi" << llendl; + LL_INFOS() << (id ? "logFromStatic: " : "") << "hi" << LL_ENDL; return "logFromStatic"; } @@ -320,7 +318,7 @@ namespace { std::string logFromAnon(bool id) { - llinfos << (id ? "logFromAnon: " : "") << "hi" << llendl; + LL_INFOS() << (id ? "logFromAnon: " : "") << "hi" << LL_ENDL; return "logFromAnon"; } } @@ -328,7 +326,7 @@ namespace namespace Foo { std::string logFromNamespace(bool id) { - llinfos << (id ? "Foo::logFromNamespace: " : "") << "hi" << llendl; + LL_INFOS() << (id ? "Foo::logFromNamespace: " : "") << "hi" << LL_ENDL; //return "Foo::logFromNamespace"; // there is no standard way to get the namespace name, hence // we won't be testing for it @@ -342,12 +340,12 @@ namespace public: std::string logFromMember(bool id) { - llinfos << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << llendl; + LL_INFOS() << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << LL_ENDL; return "ClassWithNoLogType::logFromMember"; } static std::string logFromStatic(bool id) { - llinfos << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << llendl; + LL_INFOS() << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << LL_ENDL; return "ClassWithNoLogType::logFromStatic"; } }; @@ -357,12 +355,12 @@ namespace public: std::string logFromMember(bool id) { - llinfos << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << llendl; + LL_INFOS() << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << LL_ENDL; return "ClassWithLogType::logFromMember"; } static std::string logFromStatic(bool id) { - llinfos << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << llendl; + LL_INFOS() << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << LL_ENDL; return "ClassWithLogType::logFromStatic"; } }; @@ -434,19 +432,19 @@ namespace { std::string innerLogger() { - llinfos << "inside" << llendl; + LL_INFOS() << "inside" << LL_ENDL; return "moo"; } std::string outerLogger() { - llinfos << "outside(" << innerLogger() << ")" << llendl; + LL_INFOS() << "outside(" << innerLogger() << ")" << LL_ENDL; return "bar"; } void uberLogger() { - llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl; + LL_INFOS() << "uber(" << outerLogger() << "," << innerLogger() << ")" << LL_ENDL; } class LogWhileLogging @@ -454,7 +452,7 @@ namespace public: void print(std::ostream& out) const { - llinfos << "logging" << llendl; + LL_INFOS() << "logging" << LL_ENDL; out << "baz"; } }; @@ -465,7 +463,7 @@ namespace void metaLogger() { LogWhileLogging l; - llinfos << "meta(" << l << ")" << llendl; + LL_INFOS() << "meta(" << l << ")" << LL_ENDL; } } @@ -495,7 +493,7 @@ namespace tut } template<> template<> - // special handling of llerrs calls + // special handling of LL_ERRS() calls void ErrorTestObject::test<8>() { LLError::setPrintLocation(false); @@ -518,7 +516,7 @@ namespace void ufoSighting() { - llinfos << "ufo" << llendl; + LL_INFOS() << "ufo" << LL_ENDL; } } @@ -548,11 +546,13 @@ namespace tut LLError::setPrintLocation(true); LLError::setTimeFunction(roswell); mRecorder->setWantsTime(true); - std::string locationAndFunction = writeReturningLocationAndFunction(); + std::string location, + function; + writeReturningLocationAndFunction(location, function); - ensure_equals("order is time type location function message", + ensure_equals("order is location time type function message", mRecorder->message(0), - roswell() + " INFO: " + locationAndFunction + ": apple"); + location + roswell() + " INFO: " + function + ": apple"); } template<> template<> @@ -562,7 +562,7 @@ namespace tut TestRecorder* altRecorder(new TestRecorder); LLError::addRecorder(altRecorder); - llinfos << "boo" << llendl; + LL_INFOS() << "boo" << LL_ENDL; ensure_message_contains(0, "boo"); ensure_equals("alt recorder count", altRecorder->countMessages(), 1); @@ -574,7 +574,7 @@ namespace tut anotherRecorder->setWantsTime(true); LLError::addRecorder(anotherRecorder); - llinfos << "baz" << llendl; + LL_INFOS() << "baz" << LL_ENDL; std::string when = roswell(); @@ -590,10 +590,10 @@ class TestAlpha { LOG_CLASS(TestAlpha); public: - static void doDebug() { lldebugs << "add dice" << llendl; } - static void doInfo() { llinfos << "any idea" << llendl; } - static void doWarn() { llwarns << "aim west" << llendl; } - static void doError() { llerrs << "ate eels" << llendl; } + static void doDebug() { LL_DEBUGS() << "add dice" << LL_ENDL; } + static void doInfo() { LL_INFOS() << "any idea" << LL_ENDL; } + static void doWarn() { LL_WARNS() << "aim west" << LL_ENDL; } + static void doError() { LL_ERRS() << "ate eels" << LL_ENDL; } static void doAll() { doDebug(); doInfo(); doWarn(); doError(); } }; @@ -601,10 +601,10 @@ class TestBeta { LOG_CLASS(TestBeta); public: - static void doDebug() { lldebugs << "bed down" << llendl; } - static void doInfo() { llinfos << "buy iron" << llendl; } - static void doWarn() { llwarns << "bad word" << llendl; } - static void doError() { llerrs << "big easy" << llendl; } + static void doDebug() { LL_DEBUGS() << "bed down" << LL_ENDL; } + static void doInfo() { LL_INFOS() << "buy iron" << LL_ENDL; } + static void doWarn() { LL_WARNS() << "bad word" << LL_ENDL; } + static void doError() { LL_ERRS() << "big easy" << LL_ENDL; } static void doAll() { doDebug(); doInfo(); doWarn(); doError(); } }; diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index 4d436e8897..235008a5ae 100755 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -268,7 +268,7 @@ namespace tut { std::stringstream stream; mFormatter->format(v, stream); - //llinfos << "checkRoundTrip: length " << stream.str().length() << llendl; + //LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL; LLSD w; mParser->reset(); // reset() call is needed since test code re-uses mParser mParser->parse(stream, w, stream.str().size()); diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp index e631f18ad4..ff981ca2ff 100644 --- a/indra/llcommon/tests/llunits_test.cpp +++ b/indra/llcommon/tests/llunits_test.cpp @@ -53,6 +53,7 @@ namespace tut template<> template<> void units_object_t::test<1>() { + LL_INFOS("test") << "Test" << LL_ENDL; LLUnit<F32, Quatloos> float_quatloos; ensure(float_quatloos == 0.f); @@ -93,6 +94,11 @@ namespace tut LLUnit<F32, Solari> solari(quatloos); ensure(solari == 4096); + + // division of integral unit + LLUnit<S32, Quatloos> single_quatloo(1); + LLUnit<F32, Latinum> quarter_latinum = single_quatloo; + ensure(quarter_latinum == 0.25f); } // conversions across non-base units |