diff options
Diffstat (limited to '')
-rw-r--r-- | linden/indra/llcommon/llerror.cpp | 69 |
1 files changed, 63 insertions, 6 deletions
diff --git a/linden/indra/llcommon/llerror.cpp b/linden/indra/llcommon/llerror.cpp index 0e7db89..b74b288 100644 --- a/linden/indra/llcommon/llerror.cpp +++ b/linden/indra/llcommon/llerror.cpp | |||
@@ -408,6 +408,8 @@ namespace LLError | |||
408 | LevelMap functionLevelMap; | 408 | LevelMap functionLevelMap; |
409 | LevelMap classLevelMap; | 409 | LevelMap classLevelMap; |
410 | LevelMap fileLevelMap; | 410 | LevelMap fileLevelMap; |
411 | LevelMap tagLevelMap; | ||
412 | std::map<std::string, unsigned int> uniqueLogMessages; | ||
411 | 413 | ||
412 | LLError::FatalFunction crashFunction; | 414 | LLError::FatalFunction crashFunction; |
413 | LLError::TimeFunction timeFunction; | 415 | LLError::TimeFunction timeFunction; |
@@ -494,11 +496,17 @@ namespace LLError | |||
494 | namespace LLError | 496 | namespace LLError |
495 | { | 497 | { |
496 | CallSite::CallSite(ELevel level, | 498 | CallSite::CallSite(ELevel level, |
497 | const char* file, int line, | 499 | const char* file, |
498 | const std::type_info& class_info, const char* function) | 500 | int line, |
501 | const std::type_info& class_info, | ||
502 | const char* function, | ||
503 | const char* broadTag, | ||
504 | const char* narrowTag, | ||
505 | bool printOnce) | ||
499 | : mLevel(level), mFile(file), mLine(line), | 506 | : mLevel(level), mFile(file), mLine(line), |
500 | mClassInfo(class_info), mFunction(function), | 507 | mClassInfo(class_info), mFunction(function), |
501 | mCached(false), mShouldLog(false) | 508 | mCached(false), mShouldLog(false), |
509 | mBroadTag(broadTag), mNarrowTag(narrowTag), mPrintOnce(printOnce) | ||
502 | { } | 510 | { } |
503 | 511 | ||
504 | 512 | ||
@@ -552,6 +560,15 @@ namespace | |||
552 | #endif | 560 | #endif |
553 | 561 | ||
554 | LogControlFile& e = LogControlFile::fromDirectory(dir); | 562 | LogControlFile& e = LogControlFile::fromDirectory(dir); |
563 | |||
564 | // NOTE: We want to explicitly load the file before we add it to the event timer | ||
565 | // that checks for changes to the file. Else, we're not actually loading the file yet, | ||
566 | // and most of the initialization happens without any attention being paid to the | ||
567 | // log control file. Not to mention that when it finally gets checked later, | ||
568 | // all log statements that have been evaluated already become dirty and need to be | ||
569 | // evaluated for printing again. So, make sure to call checkAndReload() | ||
570 | // before addToEventTimer(). | ||
571 | e.checkAndReload(); | ||
555 | e.addToEventTimer(); | 572 | e.addToEventTimer(); |
556 | } | 573 | } |
557 | } | 574 | } |
@@ -625,6 +642,14 @@ namespace LLError | |||
625 | g.invalidateCallSites(); | 642 | g.invalidateCallSites(); |
626 | s.fileLevelMap[file_name] = level; | 643 | s.fileLevelMap[file_name] = level; |
627 | } | 644 | } |
645 | |||
646 | void setTagLevel(const std::string& tag_name, ELevel level) | ||
647 | { | ||
648 | Globals& g = Globals::get(); | ||
649 | Settings& s = Settings::get(); | ||
650 | g.invalidateCallSites(); | ||
651 | s.tagLevelMap[tag_name] = level; | ||
652 | } | ||
628 | } | 653 | } |
629 | 654 | ||
630 | namespace { | 655 | namespace { |
@@ -674,6 +699,8 @@ namespace LLError | |||
674 | s.functionLevelMap.clear(); | 699 | s.functionLevelMap.clear(); |
675 | s.classLevelMap.clear(); | 700 | s.classLevelMap.clear(); |
676 | s.fileLevelMap.clear(); | 701 | s.fileLevelMap.clear(); |
702 | s.tagLevelMap.clear(); | ||
703 | s.uniqueLogMessages.clear(); | ||
677 | 704 | ||
678 | setPrintLocation(config["print-location"]); | 705 | setPrintLocation(config["print-location"]); |
679 | setDefaultLevel(decodeLevel(config["default-level"])); | 706 | setDefaultLevel(decodeLevel(config["default-level"])); |
@@ -689,6 +716,7 @@ namespace LLError | |||
689 | setLevels(s.functionLevelMap, entry["functions"], level); | 716 | setLevels(s.functionLevelMap, entry["functions"], level); |
690 | setLevels(s.classLevelMap, entry["classes"], level); | 717 | setLevels(s.classLevelMap, entry["classes"], level); |
691 | setLevels(s.fileLevelMap, entry["files"], level); | 718 | setLevels(s.fileLevelMap, entry["files"], level); |
719 | setLevels(s.tagLevelMap, entry["tags"], level); | ||
692 | } | 720 | } |
693 | } | 721 | } |
694 | } | 722 | } |
@@ -850,7 +878,7 @@ namespace { | |||
850 | return false; | 878 | return false; |
851 | } | 879 | } |
852 | 880 | ||
853 | level = i->second; | 881 | level = i->second; |
854 | return true; | 882 | return true; |
855 | } | 883 | } |
856 | 884 | ||
@@ -929,9 +957,15 @@ namespace LLError | |||
929 | 957 | ||
930 | ELevel compareLevel = s.defaultLevel; | 958 | ELevel compareLevel = s.defaultLevel; |
931 | 959 | ||
932 | checkLevelMap(s.functionLevelMap, function_name, compareLevel) | 960 | // The most specific match found will be used as the log level, |
961 | // since the computation short circuits. | ||
962 | // So, in increasing order of importance: | ||
963 | // Default < Broad Tag < File < Class < Function < Narrow Tag | ||
964 | ((site.mNarrowTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mNarrowTag, compareLevel) : false) | ||
965 | || checkLevelMap(s.functionLevelMap, function_name, compareLevel) | ||
933 | || checkLevelMap(s.classLevelMap, class_name, compareLevel) | 966 | || checkLevelMap(s.classLevelMap, class_name, compareLevel) |
934 | || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel); | 967 | || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel) |
968 | || ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false); | ||
935 | 969 | ||
936 | site.mCached = true; | 970 | site.mCached = true; |
937 | g.addCallSite(site); | 971 | g.addCallSite(site); |
@@ -1018,6 +1052,29 @@ namespace LLError | |||
1018 | #endif | 1052 | #endif |
1019 | prefix << site.mFunction << ": "; | 1053 | prefix << site.mFunction << ": "; |
1020 | } | 1054 | } |
1055 | |||
1056 | if (site.mPrintOnce) | ||
1057 | { | ||
1058 | std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message); | ||
1059 | if (messageIter != s.uniqueLogMessages.end()) | ||
1060 | { | ||
1061 | messageIter->second++; | ||
1062 | unsigned int num_messages = messageIter->second; | ||
1063 | if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0) | ||
1064 | { | ||
1065 | prefix << "ONCE (" << num_messages << "th time seen): "; | ||
1066 | } | ||
1067 | else | ||
1068 | { | ||
1069 | return; | ||
1070 | } | ||
1071 | } | ||
1072 | else | ||
1073 | { | ||
1074 | prefix << "ONCE: "; | ||
1075 | s.uniqueLogMessages[message] = 1; | ||
1076 | } | ||
1077 | } | ||
1021 | 1078 | ||
1022 | prefix << message; | 1079 | prefix << message; |
1023 | message = prefix.str(); | 1080 | message = prefix.str(); |