summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorRichard Linden <none@none>2013-08-12 20:05:16 -0700
committerRichard Linden <none@none>2013-08-12 20:05:16 -0700
commitcc31b4ae7934010762b8aaaa7e190c74a1cd7820 (patch)
tree61bb7e622417a5223fa108522e16f6b7dee147f3 /indra/llcommon
parente340009fc59d59e59b2e8d903a884acb76b178eb (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-xindra/llcommon/llerror.cpp507
-rwxr-xr-xindra/llcommon/llerror.h79
-rwxr-xr-xindra/llcommon/llerrorcontrol.h20
-rw-r--r--indra/llcommon/lltrace.cpp2
-rw-r--r--indra/llcommon/lltrace.h10
-rw-r--r--indra/llcommon/lltraceaccumulators.h12
-rw-r--r--indra/llcommon/lltracerecording.cpp150
-rw-r--r--indra/llcommon/lltracerecording.h87
-rw-r--r--indra/llcommon/llunit.h64
-rwxr-xr-xindra/llcommon/tests/commonmisc_test.cpp10
-rwxr-xr-xindra/llcommon/tests/llerror_test.cpp90
-rwxr-xr-xindra/llcommon/tests/llsdserialize_test.cpp2
-rw-r--r--indra/llcommon/tests/llunits_test.cpp6
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