bool Log::shouldLog(CallSite& site) { LogLock lock; if (!lock.ok()) { return false; } AIAccess<Settings> settings_w(Settings::get()); settings_w->shouldLogCallCounter += 1; std::string class_name = className(site.mClassInfo); std::string function_name = functionName(site.mFunction); if (site.mClassInfo != typeid(NoClassInfo)) { function_name = class_name + "::" + function_name; } ELevel compareLevel = settings_w->defaultLevel; // 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(settings_w->tagLevelMap, site.mNarrowTag, compareLevel) : false) || checkLevelMap(settings_w->functionLevelMap, function_name, compareLevel) || checkLevelMap(settings_w->classLevelMap, class_name, compareLevel) || checkLevelMap(settings_w->fileLevelMap, abbreviateFile(site.mFile), compareLevel) || ((site.mBroadTag != NULL) ? checkLevelMap(settings_w->tagLevelMap, site.mBroadTag, compareLevel) : false); site.mCached = true; AIAccess<Globals>(Globals::get())->addCallSite(site); return site.mShouldLog = site.mLevel >= compareLevel; }
void logToFile(const std::string& file_name) { AIAccess<Settings> settings_w(Settings::get()); removeRecorder(settings_w, settings_w->fileRecorder); delete settings_w->fileRecorder; settings_w->fileRecorder = NULL; settings_w->fileRecorderFileName.clear(); if (file_name.empty()) { return; } RecordToFile* f = new RecordToFile(file_name); if (!f->okay()) { delete f; return; } settings_w->fileRecorderFileName = file_name; settings_w->fileRecorder = f; addRecorder(settings_w, f); }
void configure(const LLSD& config) { AIAccess<Settings> settings_w(Settings::get()); AIAccess<Globals>(Globals::get())->invalidateCallSites(); settings_w->functionLevelMap.clear(); settings_w->classLevelMap.clear(); settings_w->fileLevelMap.clear(); settings_w->tagLevelMap.clear(); settings_w->uniqueLogMessages.clear(); setPrintLocation(settings_w, config["print-location"]); setDefaultLevel(settings_w, decodeLevel(config["default-level"])); LLSD sets = config["settings"]; LLSD::array_const_iterator a, end; for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a) { const LLSD& entry = *a; ELevel level = decodeLevel(entry["level"]); setLevels(settings_w->functionLevelMap, entry["functions"], level); setLevels(settings_w->classLevelMap, entry["classes"], level); setLevels(settings_w->fileLevelMap, entry["files"], level); setLevels(settings_w->tagLevelMap, entry["tags"], level); } }
void logToFixedBuffer(LLLineBuffer* fixedBuffer) { AIAccess<Settings> settings_w(Settings::get()); removeRecorder(settings_w, settings_w->fixedBufferRecorder); delete settings_w->fixedBufferRecorder; settings_w->fixedBufferRecorder = NULL; if (!fixedBuffer) { return; } settings_w->fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer); addRecorder(settings_w, settings_w->fixedBufferRecorder); }
void Log::flush(std::ostringstream* out, const CallSite& site) { LogLock lock; if (!lock.ok()) { return; } std::string message = out->str(); { AIAccess<Globals> globals(Globals::get()); if (out == &globals->messageStream) { globals->messageStream.clear(); globals->messageStream.str(""); globals->messageStreamInUse = false; } else { delete out; } } AIAccess<Settings> settings_w(Settings::get()); if (site.mLevel == LEVEL_ERROR) { std::ostringstream fatalMessage; fatalMessage << abbreviateFile(site.mFile) << "(" << site.mLine << ") : error"; writeToRecorders(settings_w, site.mLevel, fatalMessage.str()); } 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 (settings_w->printLocation) { prefix << abbreviateFile(site.mFile) << "(" << site.mLine << ") : "; } #if LL_WINDOWS // DevStudio: __FUNCTION__ already includes the full class name #else if (site.mClassInfo != typeid(NoClassInfo)) { prefix << className(site.mClassInfo) << "::"; } #endif prefix << site.mFunction << ": "; if (site.mPrintOnce) { std::map<std::string, unsigned int>::iterator messageIter = settings_w->uniqueLogMessages.find(message); if (messageIter != settings_w->uniqueLogMessages.end()) { messageIter->second++; unsigned int num_messages = messageIter->second; if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0) { prefix << "ONCE (" << num_messages << "th time seen): "; } else { return; } } else { prefix << "ONCE: "; settings_w->uniqueLogMessages[message] = 1; } } if (site.mPrintOnce) { std::map<std::string, unsigned int>::iterator messageIter = settings_w->uniqueLogMessages.find(message); if (messageIter != settings_w->uniqueLogMessages.end()) { messageIter->second++; unsigned int num_messages = messageIter->second; if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0) { prefix << "ONCE (" << num_messages << "th time seen): "; } else { return; } } else { prefix << "ONCE: "; settings_w->uniqueLogMessages[message] = 1; } } prefix << message; message = prefix.str(); writeToRecorders(settings_w, site.mLevel, message); if (site.mLevel == LEVEL_ERROR && settings_w->crashFunction) { settings_w->crashFunction(message); } }
void Log::flush(std::ostringstream* out, const CallSite& site) { LogLock lock; if (!lock.ok()) { return; } std::string message = out->str(); { AIAccess<Globals> globals(Globals::get()); if (out == &globals->messageStream) { globals->messageStream.clear(); globals->messageStream.str(""); globals->messageStreamInUse = false; } else { delete out; } } AIAccess<Settings> settings_w(Settings::get()); if (site.mLevel == LEVEL_ERROR) { std::ostringstream fatalMessage; fatalMessage << abbreviateFile(site.mFile) << "(" << site.mLine << ") : error"; writeToRecorders(settings_w, site.mLevel, fatalMessage.str()); } 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; }; bool need_function = site.mFunction; if (need_function && site.mBroadTag && *site.mBroadTag != '\0') { prefix << "(\"" << site.mBroadTag << "\")"; #if LL_DEBUG // Suppress printing mFunction if mBroadTag is set, starts with // "Plugin " and ends with "child": a debug message from a plugin. size_t taglen = strlen(site.mBroadTag); if (taglen >= 12 && strncmp(site.mBroadTag, "Plugin ", 7) == 0 && strcmp(site.mBroadTag + taglen - 5, "child") == 0) { need_function = false; } #endif } prefix << ": "; if (need_function) { if (settings_w->printLocation) { prefix << abbreviateFile(site.mFile) << "(" << site.mLine << ") : "; } #if LL_WINDOWS // DevStudio: __FUNCTION__ already includes the full class name #else if (site.mClassInfo != typeid(NoClassInfo)) { prefix << className(site.mClassInfo) << "::"; } #endif prefix << site.mFunction << ": "; } if (site.mPrintOnce) { std::map<std::string, unsigned int>::iterator messageIter = settings_w->uniqueLogMessages.find(message); if (messageIter != settings_w->uniqueLogMessages.end()) { messageIter->second++; unsigned int num_messages = messageIter->second; if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0) { prefix << "ONCE (" << num_messages << "th time seen): "; } else { return; } } else { prefix << "ONCE: "; settings_w->uniqueLogMessages[message] = 1; } } if (site.mPrintOnce) { std::map<std::string, unsigned int>::iterator messageIter = settings_w->uniqueLogMessages.find(message); if (messageIter != settings_w->uniqueLogMessages.end()) { messageIter->second++; unsigned int num_messages = messageIter->second; if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0) { prefix << "ONCE (" << num_messages << "th time seen): "; } else { return; } } else { prefix << "ONCE: "; settings_w->uniqueLogMessages[message] = 1; } } prefix << message; message = prefix.str(); writeToRecorders(settings_w, site.mLevel, message); if (site.mLevel == LEVEL_ERROR && settings_w->crashFunction) { settings_w->crashFunction(message); } }