diff --git a/include/loot/api.h b/include/loot/api.h index 2984aa4b..f3baa6ac 100644 --- a/include/loot/api.h +++ b/include/loot/api.h @@ -57,6 +57,15 @@ namespace loot { LOOT_API void SetLoggingCallback( std::function 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 diff --git a/src/api/api.cpp b/src/api/api.cpp index c08ccedf..2ce689ad 100644 --- a/src/api/api.cpp +++ b/src/api/api.cpp @@ -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) { diff --git a/src/api/helpers/logging.cpp b/src/api/helpers/logging.cpp index c13293d1..41712dd0 100644 --- a/src/api/helpers/logging.cpp +++ b/src/api/helpers/logging.cpp @@ -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 { public: explicit SpdLoggingSink(std::function callback) { @@ -83,4 +103,11 @@ std::shared_ptr createLogger( return logger; } + +void setLoggerLevel(LogLevel level) { + auto logger = getLogger(); + if (logger) { + logger->set_level(mapToSpdlog(level)); + } +} } diff --git a/src/api/helpers/logging.h b/src/api/helpers/logging.h index a948c4e4..cce669b0 100644 --- a/src/api/helpers/logging.h +++ b/src/api/helpers/logging.h @@ -33,6 +33,8 @@ std::shared_ptr getLogger(); std::shared_ptr createLogger( std::function callback); + +void setLoggerLevel(LogLevel level); } #endif diff --git a/src/tests/api/interface/main.cpp b/src/tests/api/interface/main.cpp index 405173f4..34ffffd5 100644 --- a/src/tests/api/interface/main.cpp +++ b/src/tests/api/interface/main.cpp @@ -122,5 +122,37 @@ TEST(SetLoggingCallback, SetLoggingCallback([](LogLevel, const char *) {}); } } + +TEST(SetLogLevel, shouldOnlyRunTheCallbackForMessagesAtOrAboveTheGivenLevel) { + std::vector> 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 *) {}); + } +} } }