summaryrefslogtreecommitdiff
path: root/indra/llcommon/llerror.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon/llerror.cpp')
-rwxr-xr-xindra/llcommon/llerror.cpp799
1 files changed, 432 insertions, 367 deletions
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 853f279c95..22cd861c72 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -47,11 +47,31 @@
#include "lllivefile.h"
#include "llsd.h"
#include "llsdserialize.h"
+#include "llsingleton.h"
#include "llstl.h"
#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:
@@ -96,8 +116,9 @@ namespace {
mFile.open(filename, llofstream::out | llofstream::app);
if (!mFile)
{
- llinfos << "Error setting log file to " << filename << llendl;
+ LL_INFOS() << "Error setting log file to " << filename << LL_ENDL;
}
+ mWantsTime = true;
}
~RecordToFile()
@@ -107,14 +128,10 @@ namespace {
bool okay() { return mFile; }
- virtual bool wantsTime() { return true; }
-
virtual void recordMessage(LLError::ELevel level,
const std::string& message)
{
mFile << message << std::endl;
- // mFile.flush();
- // *FIX: should we do this?
}
private:
@@ -125,9 +142,10 @@ namespace {
class RecordToStderr : public LLError::Recorder
{
public:
- RecordToStderr(bool timestamp) : mTimestamp(timestamp), mUseANSI(ANSI_PROBE) { }
-
- virtual bool wantsTime() { return mTimestamp; }
+ RecordToStderr(bool timestamp) : mUseANSI(ANSI_PROBE)
+ {
+ mWantsTime = timestamp;
+ }
virtual void recordMessage(LLError::ELevel level,
const std::string& message)
@@ -158,14 +176,19 @@ namespace {
}
private:
- bool mTimestamp;
- enum ANSIState {ANSI_PROBE, ANSI_YES, ANSI_NO};
- ANSIState mUseANSI;
+ enum ANSIState
+ {
+ ANSI_PROBE,
+ ANSI_YES,
+ ANSI_NO
+ } mUseANSI;
+
void colorANSI(const std::string color)
{
// ANSI color code escape sequence
fprintf(stderr, "\033[%sm", color.c_str() );
};
+
bool checkANSI(void)
{
#if LL_LINUX || LL_DARWIN
@@ -198,10 +221,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
@@ -213,7 +239,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);
@@ -317,44 +343,45 @@ namespace
if (configuration.isUndefined())
{
- llwarns << filename() << " missing, ill-formed,"
+ LL_WARNS() << filename() << " missing, ill-formed,"
" or simply undefined; not changing configuration"
- << llendl;
+ << LL_ENDL;
return false;
}
}
LLError::configure(configuration);
- llinfos << "logging reconfigured from " << filename() << llendl;
+ LL_INFOS() << "logging reconfigured from " << filename() << LL_ENDL;
return true;
}
typedef std::map<std::string, LLError::ELevel> LevelMap;
- typedef std::vector<LLError::Recorder*> Recorders;
+ typedef std::vector<LLError::RecorderPtr> Recorders;
typedef std::vector<LLError::CallSite*> CallSiteVector;
- class Globals
+ class Globals : public LLSingleton<Globals>
{
public:
+ Globals();
+
std::ostringstream messageStream;
bool messageStreamInUse;
void addCallSite(LLError::CallSite&);
void invalidateCallSites();
-
- static Globals& get();
- // return the one instance of the globals
private:
CallSiteVector callSites;
-
- Globals()
- : messageStreamInUse(false)
- { }
-
};
+ Globals::Globals()
+ : messageStream(),
+ messageStreamInUse(false),
+ callSites()
+ {
+ }
+
void Globals::addCallSite(LLError::CallSite& site)
{
callSites.push_back(&site);
@@ -371,114 +398,111 @@ namespace
callSites.clear();
}
-
- Globals& Globals::get()
- {
- /* This pattern, of returning a reference to a static function
- variable, is to ensure that this global is constructed before
- it is used, no matter what the global initialization sequence
- is.
- See C++ FAQ Lite, sections 10.12 through 10.14
- */
- static Globals* globals = new Globals;
- return *globals;
- }
}
namespace LLError
{
- class Settings
+ class SettingsConfig : public LLRefCount
{
+ friend class Settings;
+
public:
- bool printLocation;
+ virtual ~SettingsConfig();
+
+ bool mPrintLocation;
- LLError::ELevel defaultLevel;
+ LLError::ELevel mDefaultLevel;
- LevelMap functionLevelMap;
- LevelMap classLevelMap;
- LevelMap fileLevelMap;
- LevelMap tagLevelMap;
- std::map<std::string, unsigned int> uniqueLogMessages;
+ LevelMap mFunctionLevelMap;
+ LevelMap mClassLevelMap;
+ LevelMap mFileLevelMap;
+ LevelMap mTagLevelMap;
+ std::map<std::string, unsigned int> mUniqueLogMessages;
- LLError::FatalFunction crashFunction;
- LLError::TimeFunction timeFunction;
+ LLError::FatalFunction mCrashFunction;
+ LLError::TimeFunction mTimeFunction;
- Recorders recorders;
- Recorder* fileRecorder;
- Recorder* fixedBufferRecorder;
- std::string fileRecorderFileName;
+ Recorders mRecorders;
+ RecorderPtr mFileRecorder;
+ RecorderPtr mFixedBufferRecorder;
+ std::string mFileRecorderFileName;
- int shouldLogCallCounter;
+ int mShouldLogCallCounter;
- static Settings& get();
+ private:
+ SettingsConfig();
+ };
+
+ typedef LLPointer<SettingsConfig> SettingsConfigPtr;
+
+ class Settings : public LLSingleton<Settings>
+ {
+ public:
+ Settings();
+
+ SettingsConfigPtr getSettingsConfig();
- static void reset();
- static Settings* saveAndReset();
- static void restore(Settings*);
+ void reset();
+ SettingsStoragePtr saveAndReset();
+ void restore(SettingsStoragePtr pSettingsStorage);
private:
- Settings()
- : printLocation(false),
- defaultLevel(LLError::LEVEL_DEBUG),
- crashFunction(),
- timeFunction(NULL),
- fileRecorder(NULL),
- fixedBufferRecorder(NULL),
- shouldLogCallCounter(0)
- { }
-
- ~Settings()
- {
- for_each(recorders.begin(), recorders.end(), DeletePointer());
- recorders.clear();
- }
-
- static Settings*& getPtr();
+ SettingsConfigPtr mSettingsConfig;
};
- Settings& Settings::get()
+ SettingsConfig::SettingsConfig()
+ : LLRefCount(),
+ mPrintLocation(false),
+ mDefaultLevel(LLError::LEVEL_DEBUG),
+ mFunctionLevelMap(),
+ mClassLevelMap(),
+ mFileLevelMap(),
+ mTagLevelMap(),
+ mUniqueLogMessages(),
+ mCrashFunction(NULL),
+ mTimeFunction(NULL),
+ mRecorders(),
+ mFileRecorder(),
+ mFixedBufferRecorder(),
+ mFileRecorderFileName(),
+ mShouldLogCallCounter(0)
{
- Settings* p = getPtr();
- if (!p)
- {
- reset();
- p = getPtr();
- }
- return *p;
}
-
- void Settings::reset()
+
+ SettingsConfig::~SettingsConfig()
+ {
+ mRecorders.clear();
+ }
+
+ Settings::Settings()
+ : LLSingleton<Settings>(),
+ mSettingsConfig(new SettingsConfig())
{
- Globals::get().invalidateCallSites();
-
- Settings*& p = getPtr();
- delete p;
- p = new Settings();
+ }
+
+ SettingsConfigPtr Settings::getSettingsConfig()
+ {
+ return mSettingsConfig;
}
- Settings* Settings::saveAndReset()
+ void Settings::reset()
{
- Globals::get().invalidateCallSites();
-
- Settings*& p = getPtr();
- Settings* originalSettings = p;
- p = new Settings();
- return originalSettings;
+ Globals::getInstance()->invalidateCallSites();
+ mSettingsConfig = new SettingsConfig();
}
- void Settings::restore(Settings* originalSettings)
+ SettingsStoragePtr Settings::saveAndReset()
{
- Globals::get().invalidateCallSites();
-
- Settings*& p = getPtr();
- delete p;
- p = originalSettings;
+ SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());
+ reset();
+ return oldSettingsConfig;
}
- Settings*& Settings::getPtr()
+ void Settings::restore(SettingsStoragePtr pSettingsStorage)
{
- static Settings* currentSettings = NULL;
- return currentSettings;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
+ mSettingsConfig = newSettingsConfig;
}
}
@@ -489,18 +513,64 @@ namespace LLError
int line,
const std::type_info& class_info,
const char* function,
- const char* broadTag,
- const char* narrowTag,
- bool printOnce)
- : mLevel(level), mFile(file), mLine(line),
- mClassInfo(class_info), mFunction(function),
- mCached(false), mShouldLog(false),
- mBroadTag(broadTag), mNarrowTag(narrowTag), mPrintOnce(printOnce)
- { }
+ bool printOnce,
+ const char** tags,
+ size_t tag_count)
+ : mLevel(level),
+ mFile(file),
+ mLine(line),
+ mClassInfo(class_info),
+ mFunction(function),
+ mCached(false),
+ mShouldLog(false),
+ mPrintOnce(printOnce),
+ mTags(new const char* [tag_count]),
+ mTagCount(tag_count)
+ {
+ 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(mClassInfo.name(), typeid(NoClassInfo).name()))
+#else
+ if (mClassInfo != typeid(NoClassInfo))
+#endif // LL_LINUX
+ {
+ mFunctionString = className(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
@@ -533,7 +603,7 @@ namespace
void commonInit(const std::string& dir, bool log_to_stderr = true)
{
- LLError::Settings::reset();
+ LLError::Settings::getInstance()->reset();
LLError::setDefaultLevel(LLError::LEVEL_INFO);
LLError::setFatalFunction(LLError::crashAndLoop);
@@ -542,11 +612,13 @@ namespace
// log_to_stderr is only false in the unit and integration tests to keep builds quieter
if (log_to_stderr && shouldLogToStderr())
{
- LLError::addRecorder(new RecordToStderr(stderrLogWantsTime()));
+ LLError::RecorderPtr recordToStdErr(new RecordToStderr(stderrLogWantsTime()));
+ LLError::addRecorder(recordToStdErr);
}
#if LL_WINDOWS
- LLError::addRecorder(new RecordToWinDebug);
+ LLError::RecorderPtr recordToWinDebug(new RecordToWinDebug());
+ LLError::addRecorder(recordToWinDebug);
#endif
LogControlFile& e = LogControlFile::fromDirectory(dir);
@@ -574,7 +646,8 @@ namespace LLError
}
commonInit(dir);
#if !LL_WINDOWS
- addRecorder(new RecordToSyslog(identity));
+ LLError::RecorderPtr recordToSyslog(new RecordToSyslog(identity));
+ addRecorder(recordToSyslog);
#endif
}
@@ -585,72 +658,67 @@ namespace LLError
void setPrintLocation(bool print)
{
- Settings& s = Settings::get();
- s.printLocation = print;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mPrintLocation = print;
}
void setFatalFunction(const FatalFunction& f)
{
- Settings& s = Settings::get();
- s.crashFunction = f;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mCrashFunction = f;
}
FatalFunction getFatalFunction()
{
- Settings& s = Settings::get();
- return s.crashFunction;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ return s->mCrashFunction;
}
void setTimeFunction(TimeFunction f)
{
- Settings& s = Settings::get();
- s.timeFunction = f;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mTimeFunction = f;
}
void setDefaultLevel(ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.defaultLevel = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mDefaultLevel = level;
}
ELevel getDefaultLevel()
{
- Settings& s = Settings::get();
- return s.defaultLevel;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ return s->mDefaultLevel;
}
void setFunctionLevel(const std::string& function_name, ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.functionLevelMap[function_name] = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mFunctionLevelMap[function_name] = level;
}
void setClassLevel(const std::string& class_name, ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.classLevelMap[class_name] = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mClassLevelMap[class_name] = level;
}
void setFileLevel(const std::string& file_name, ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.fileLevelMap[file_name] = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mFileLevelMap[file_name] = level;
}
void setTagLevel(const std::string& tag_name, ELevel level)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
- g.invalidateCallSites();
- s.tagLevelMap[tag_name] = level;
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mTagLevelMap[tag_name] = level;
}
LLError::ELevel decodeLevel(std::string name)
@@ -671,7 +739,7 @@ namespace LLError
LevelMap::const_iterator i = level_names.find(name);
if (i == level_names.end())
{
- llwarns << "unrecognized logging level: '" << name << "'" << llendl;
+ LL_WARNS() << "unrecognized logging level: '" << name << "'" << LL_ENDL;
return LLError::LEVEL_INFO;
}
@@ -694,15 +762,14 @@ namespace LLError
{
void configure(const LLSD& config)
{
- Globals& g = Globals::get();
- Settings& s = Settings::get();
+ Globals::getInstance()->invalidateCallSites();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- 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"]));
@@ -715,10 +782,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);
}
}
}
@@ -726,35 +793,67 @@ 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 mWantsTags;
+ }
+ // virtual
+ bool Recorder::wantsLevel()
+ {
+ return mWantsLevel;
+ }
- void addRecorder(Recorder* recorder)
+ // virtual
+ bool Recorder::wantsLocation()
+ {
+ return mWantsLocation;
+ }
+
+ // virtual
+ bool Recorder::wantsFunctionName()
+ {
+ return mWantsFunctionName;
+ }
+
+ void addRecorder(RecorderPtr recorder)
{
- if (recorder == NULL)
+ if (!recorder)
{
return;
}
- Settings& s = Settings::get();
- s.recorders.push_back(recorder);
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mRecorders.push_back(recorder);
}
- void removeRecorder(Recorder* recorder)
+ void removeRecorder(RecorderPtr recorder)
{
- if (recorder == NULL)
+ if (!recorder)
{
return;
}
- Settings& s = Settings::get();
- s.recorders.erase(
- std::remove(s.recorders.begin(), s.recorders.end(), recorder),
- s.recorders.end());
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder),
+ s->mRecorders.end());
}
}
@@ -762,126 +861,136 @@ namespace LLError
{
void logToFile(const std::string& file_name)
{
- LLError::Settings& s = LLError::Settings::get();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- removeRecorder(s.fileRecorder);
- delete s.fileRecorder;
- s.fileRecorder = NULL;
- s.fileRecorderFileName.clear();
+ removeRecorder(s->mFileRecorder);
+ s->mFileRecorder.reset();
+ s->mFileRecorderFileName.clear();
if (file_name.empty())
{
return;
}
- RecordToFile* f = new RecordToFile(file_name);
- if (!f->okay())
+ RecorderPtr recordToFile(new RecordToFile(file_name));
+ if (boost::dynamic_pointer_cast<RecordToFile>(recordToFile)->okay())
{
- delete f;
- return;
+ s->mFileRecorderFileName = file_name;
+ s->mFileRecorder = recordToFile;
+ addRecorder(recordToFile);
}
-
- s.fileRecorderFileName = file_name;
- s.fileRecorder = f;
- addRecorder(f);
}
void logToFixedBuffer(LLLineBuffer* fixedBuffer)
{
- LLError::Settings& s = LLError::Settings::get();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- removeRecorder(s.fixedBufferRecorder);
- delete s.fixedBufferRecorder;
- s.fixedBufferRecorder = NULL;
+ removeRecorder(s->mFixedBufferRecorder);
+ s->mFixedBufferRecorder.reset();
if (!fixedBuffer)
{
return;
}
- s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
- addRecorder(s.fixedBufferRecorder);
+ RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer));
+ s->mFixedBufferRecorder = recordToFixedBuffer;
+ addRecorder(recordToFixedBuffer);
}
std::string logFileName()
{
- LLError::Settings& s = LLError::Settings::get();
- return s.fileRecorderFileName;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ return s->mFileRecorderFileName;
}
}
namespace
{
- void writeToRecorders(LLError::ELevel level, 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::Settings& s = LLError::Settings::get();
+ LLError::ELevel level = site.mLevel;
+ LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig();
- std::string messageWithTime;
-
- 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;
+ LLError::RecorderPtr r = *i;
- if (r->wantsTime() && s.timeFunction != NULL)
+ std::ostringstream message_stream;
+
+ if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation))
+ {
+ message_stream << site.mLocationString << " ";
+ }
+
+ if (show_time && r->wantsTime() && s->mTimeFunction != NULL)
{
- if (messageWithTime.empty())
+ message_stream << s->mTimeFunction() << " ";
+ }
+
+ if (show_level && r->wantsLevel())
{
- messageWithTime = s.timeFunction() + " " + message;
+ message_stream << site.mLevelString << " ";
}
- r->recordMessage(level, messageWithTime);
+ if (show_tags && r->wantsTags())
+ {
+ message_stream << site.mTagString << " ";
}
- else
+
+ if (show_function && r->wantsFunctionName())
{
- r->recordMessage(level, message);
+ message_stream << site.mFunctionString << " ";
}
+
+ message_stream << message;
+
+ r->recordMessage(level, message_stream.str());
}
}
}
-
-/*
-Recorder formats:
-
-$type = "ERROR" | "WARNING" | "ALERT" | "INFO" | "DEBUG"
-$loc = "$file($line)"
-$msg = "$loc : " if FATAL or printing loc
- "" otherwise
-$msg += "$type: "
-$msg += contents of stringstream
-
-$time = "%Y-%m-%dT%H:%M:%SZ" if UTC
- or "%Y-%m-%dT%H:%M:%S %Z" if local
-
-syslog: "$msg"
-file: "$time $msg\n"
-stderr: "$time $msg\n" except on windows, "$msg\n"
-fixedbuf: "$msg"
-winddebug: "$msg\n"
-
-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
-
-*/
-
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;
+ 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
@@ -945,12 +1054,11 @@ namespace LLError
return false;
}
- Globals& g = Globals::get();
- Settings& s = Settings::get();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
- s.shouldLogCallCounter += 1;
+ s->mShouldLogCallCounter++;
- std::string class_name = className(site.mClassInfo);
+ const 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
@@ -962,20 +1070,21 @@ 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);
+ Globals::getInstance()->addCallSite(site);
return site.mShouldLog = site.mLevel >= compareLevel;
}
@@ -985,12 +1094,12 @@ namespace LLError
LogLock lock;
if (lock.ok())
{
- Globals& g = Globals::get();
+ Globals* g = Globals::getInstance();
- if (!g.messageStreamInUse)
+ if (!g->messageStreamInUse)
{
- g.messageStreamInUse = true;
- return &g.messageStream;
+ g->messageStreamInUse = true;
+ return &g->messageStream;
}
}
@@ -1015,12 +1124,12 @@ namespace LLError
message[127] = '\0' ;
}
- Globals& g = Globals::get();
- if (out == &g.messageStream)
+ Globals* g = Globals::getInstance();
+ if (out == &g->messageStream)
{
- g.messageStream.clear();
- g.messageStream.str("");
- g.messageStreamInUse = false;
+ g->messageStream.clear();
+ g->messageStream.str("");
+ g->messageStreamInUse = false;
}
else
{
@@ -1037,15 +1146,15 @@ namespace LLError
return;
}
- Globals& g = Globals::get();
- Settings& s = Settings::get();
+ Globals* g = Globals::getInstance();
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
std::string message = out->str();
- if (out == &g.messageStream)
+ if (out == &g->messageStream)
{
- g.messageStream.clear();
- g.messageStream.str("");
- g.messageStreamInUse = false;
+ g->messageStream.clear();
+ g->messageStream.str("");
+ g->messageStreamInUse = false;
}
else
{
@@ -1054,56 +1163,21 @@ namespace LLError
if (site.mLevel == LEVEL_ERROR)
{
- std::ostringstream fatalMessage;
- fatalMessage << abbreviateFile(site.mFile)
- << "(" << site.mLine << ") : error";
-
- writeToRecorders(site.mLevel, fatalMessage.str());
+ writeToRecorders(site, "error", true, true, true, false, false);
}
-
- 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 << ": ";
+ std::ostringstream message_stream;
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
{
@@ -1112,36 +1186,32 @@ 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.mLevel, 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()
+ SettingsStoragePtr saveAndResetSettings()
{
- return Settings::saveAndReset();
+ return Settings::getInstance()->saveAndReset();
}
- void restoreSettings(Settings* s)
+ void restoreSettings(SettingsStoragePtr pSettingsStorage)
{
- return Settings::restore(s);
+ return Settings::getInstance()->restore(pSettingsStorage);
}
std::string removePrefix(std::string& s, const std::string& p)
@@ -1187,8 +1257,8 @@ namespace LLError
int shouldLogCallCount()
{
- Settings& s = Settings::get();
- return s.shouldLogCallCounter;
+ SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ return s->mShouldLogCallCounter;
}
#if LL_WINDOWS
@@ -1297,15 +1367,9 @@ namespace LLError
#endif
//static
- void LLCallStacks::push(const char* function, const int line)
+ void LLCallStacks::allocateStackBuffer()
{
- CallStacksLogLock lock;
- if (!lock.ok())
- {
- return;
- }
-
- if(!sBuffer)
+ if(sBuffer == NULL)
{
sBuffer = new char*[512] ;
sBuffer[0] = new char[512 * 128] ;
@@ -1315,6 +1379,31 @@ namespace LLError
}
sIndex = 0 ;
}
+ }
+
+ void LLCallStacks::freeStackBuffer()
+ {
+ if(sBuffer != NULL)
+ {
+ delete [] sBuffer[0] ;
+ delete [] sBuffer ;
+ sBuffer = NULL ;
+ }
+ }
+
+ //static
+ void LLCallStacks::push(const char* function, const int line)
+ {
+ CallStacksLogLock lock;
+ if (!lock.ok())
+ {
+ return;
+ }
+
+ if(sBuffer == NULL)
+ {
+ allocateStackBuffer();
+ }
if(sIndex > 511)
{
@@ -1346,15 +1435,9 @@ namespace LLError
return;
}
- if(!sBuffer)
+ if(sBuffer == NULL)
{
- sBuffer = new char*[512] ;
- sBuffer[0] = new char[512 * 128] ;
- for(S32 i = 1 ; i < 512 ; i++)
- {
- sBuffer[i] = sBuffer[i-1] + 128 ;
- }
- sIndex = 0 ;
+ allocateStackBuffer();
}
if(sIndex > 511)
@@ -1376,20 +1459,18 @@ namespace LLError
if(sIndex > 0)
{
- llinfos << " ************* PRINT OUT LL CALL STACKS ************* " << llendl ;
+ LL_INFOS() << " ************* PRINT OUT LL CALL STACKS ************* " << LL_ENDL;
while(sIndex > 0)
{
sIndex-- ;
- llinfos << sBuffer[sIndex] << llendl ;
+ LL_INFOS() << sBuffer[sIndex] << LL_ENDL;
}
- llinfos << " *************** END OF LL CALL STACKS *************** " << llendl ;
+ LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;
}
- if(sBuffer)
+ if(sBuffer != NULL)
{
- delete[] sBuffer[0] ;
- delete[] sBuffer ;
- sBuffer = NULL ;
+ freeStackBuffer();
}
}
@@ -1399,26 +1480,10 @@ 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
-
+ //static
+ void LLCallStacks::cleanup()
+ {
+ freeStackBuffer();
+ }
}