Add SetLogLevel() to the public API

While the callback can filter log messages to the desired level, setting the log level in libloot means that it can avoid doing work to construct error messages that may then be discarded.
This commit is contained in:
Oliver Hamlet
2025-03-15 14:38:38 +00:00
parent 1748dc7a3c
commit 2f3e61c1f5
5 changed files with 72 additions and 0 deletions
+9
View File
@@ -57,6 +57,15 @@ namespace loot {
LOOT_API void SetLoggingCallback(
std::function<void(LogLevel, const char*)> callback);
/**
* @brief Set the log severity level.
* @details The default level setting is trace. This function has no effect if
* no logging callback has been set.
* @param level
* Messages of this severity level and higher will be logged.
*/
LOOT_API void SetLogLevel(LogLevel level);
/**
* @}
* @name Version Functions
+2
View File
@@ -90,6 +90,8 @@ LOOT_API void SetLoggingCallback(
spdlog::register_logger(logger);
}
LOOT_API void SetLogLevel(LogLevel level) { setLoggerLevel(level); }
LOOT_API bool IsCompatible(const unsigned int versionMajor,
const unsigned int versionMinor,
const unsigned int) {
+27
View File
@@ -51,6 +51,26 @@ LogLevel mapFromSpdlog(spdlog::level::level_enum severity) {
}
}
spdlog::level::level_enum mapToSpdlog(LogLevel severity) {
using spdlog::level::level_enum;
switch (severity) {
case LogLevel::trace:
return level_enum::trace;
case LogLevel::debug:
return level_enum::debug;
case LogLevel::info:
return level_enum::info;
case LogLevel::warning:
return level_enum::warn;
case LogLevel::error:
return level_enum::err;
case LogLevel::fatal:
return level_enum::critical;
default:
return level_enum::trace;
}
}
class SpdLoggingSink : public spdlog::sinks::base_sink<std::mutex> {
public:
explicit SpdLoggingSink(std::function<void(LogLevel, const char*)> callback) {
@@ -83,4 +103,11 @@ std::shared_ptr<spdlog::logger> createLogger(
return logger;
}
void setLoggerLevel(LogLevel level) {
auto logger = getLogger();
if (logger) {
logger->set_level(mapToSpdlog(level));
}
}
}
+2
View File
@@ -33,6 +33,8 @@ std::shared_ptr<spdlog::logger> getLogger();
std::shared_ptr<spdlog::logger> createLogger(
std::function<void(LogLevel, const char*)> callback);
void setLoggerLevel(LogLevel level);
}
#endif
+32
View File
@@ -122,5 +122,37 @@ TEST(SetLoggingCallback,
SetLoggingCallback([](LogLevel, const char *) {});
}
}
TEST(SetLogLevel, shouldOnlyRunTheCallbackForMessagesAtOrAboveTheGivenLevel) {
std::vector<std::pair<LogLevel, std::string>> loggedMessages;
auto callback = [&](LogLevel level, const char *string) {
loggedMessages.push_back(std::make_pair(level, std::string(string)));
};
SetLoggingCallback(callback);
SetLogLevel(LogLevel::fatal);
try {
CreateGameHandle(GameType::tes4, "dummy");
FAIL();
} catch (...) {
EXPECT_TRUE(loggedMessages.empty());
}
SetLogLevel(LogLevel::info);
try {
CreateGameHandle(GameType::tes4, "dummy");
FAIL();
} catch (...) {
ASSERT_EQ(1, loggedMessages.size());
EXPECT_EQ(LogLevel::info, loggedMessages[0].first);
EXPECT_EQ(
"Attempting to create a game handle for game type \"The Elder Scrolls "
"IV: Oblivion\" with game path \"dummy\" and game local path \"\"",
loggedMessages[0].second);
SetLoggingCallback([](LogLevel, const char *) {});
}
}
}
}