# HG changeset patch # User Sebastien Jodogne # Date 1604410887 -3600 # Node ID d7a50b7b84668e540674023815ef519f454f30ed # Parent 09ed936fd38195d2baa0f1d8e82b0a1fae5c4975 Dynamically access and/or change the verbosity of logging categories with the REST API diff -r 09ed936fd381 -r d7a50b7b8466 NEWS --- a/NEWS Tue Nov 03 12:28:25 2020 +0100 +++ b/NEWS Tue Nov 03 14:41:27 2020 +0100 @@ -1,7 +1,19 @@ Pending changes in the mainline =============================== -* Logging categories (check out command-line options "--verbose=" and "--trace=") +General +------- + +* Logging categories (cf. command-line options starting with "--verbose-" and "--trace=") + +REST API +-------- + +* "/tools/log-level-*": Dynamically access and/or change the verbosity of logging categories + +Maintenance +----------- + * C-GET SCP: Fix responses and handling of cancel * Fix decoding sequence if "BuiltinDecoderTranscoderOrder" is "Before" * REST API returns 404 error if deleting an inexistent peer or modality diff -r 09ed936fd381 -r d7a50b7b8466 OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake --- a/OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake Tue Nov 03 12:28:25 2020 +0100 +++ b/OrthancFramework/Resources/CMake/OrthancFrameworkParameters.cmake Tue Nov 03 14:41:27 2020 +0100 @@ -37,7 +37,7 @@ # Version of the Orthanc API, can be retrieved from "/system" URI in # order to check whether new URI endpoints are available even if using # the mainline version of Orthanc -set(ORTHANC_API_VERSION "8") +set(ORTHANC_API_VERSION "9") ##################################################################### diff -r 09ed936fd381 -r d7a50b7b8466 OrthancFramework/Sources/Logging.cpp --- a/OrthancFramework/Sources/Logging.cpp Tue Nov 03 12:28:25 2020 +0100 +++ b/OrthancFramework/Sources/Logging.cpp Tue Nov 03 14:41:27 2020 +0100 @@ -228,29 +228,42 @@ } - size_t GetCategoriesCount() + unsigned int GetCategoriesCount() { return 5; } - const char* GetCategoryName(size_t i) + const char* GetCategoryName(unsigned int i) { - switch (i) + if (i < GetCategoriesCount()) + { + return GetCategoryName(static_cast(1 << i)); + } + else { - case 0: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + } + + + const char* GetCategoryName(LogCategory category) + { + switch (category) + { + case LogCategory_GENERIC: return "generic"; - - case 1: + + case LogCategory_PLUGINS: return "plugins"; - - case 2: + + case LogCategory_REST: return "rest"; - - case 3: + + case LogCategory_DICOM: return "dicom"; - - case 4: + + case LogCategory_SQLITE: return "sqlite"; default: diff -r 09ed936fd381 -r d7a50b7b8466 OrthancFramework/Sources/Logging.h --- a/OrthancFramework/Sources/Logging.h Tue Nov 03 12:28:25 2020 +0100 +++ b/OrthancFramework/Sources/Logging.h Tue Nov 03 14:41:27 2020 +0100 @@ -100,9 +100,11 @@ ORTHANC_PUBLIC bool LookupCategory(LogCategory& target, const std::string& category); - ORTHANC_PUBLIC size_t GetCategoriesCount(); + ORTHANC_PUBLIC unsigned int GetCategoriesCount(); - ORTHANC_PUBLIC const char* GetCategoryName(size_t i); + ORTHANC_PUBLIC const char* GetCategoryName(unsigned int i); + + ORTHANC_PUBLIC const char* GetCategoryName(LogCategory category); ORTHANC_PUBLIC void SetTargetFile(const std::string& path); diff -r 09ed936fd381 -r d7a50b7b8466 OrthancFramework/UnitTestsSources/LoggingTests.cpp --- a/OrthancFramework/UnitTestsSources/LoggingTests.cpp Tue Nov 03 12:28:25 2020 +0100 +++ b/OrthancFramework/UnitTestsSources/LoggingTests.cpp Tue Nov 03 14:41:27 2020 +0100 @@ -359,3 +359,42 @@ ASSERT_TRUE(IsCategoryEnabled(LogLevel_INFO, LogCategory_SQLITE)); ASSERT_FALSE(IsCategoryEnabled(LogLevel_TRACE, LogCategory_SQLITE)); } + + +TEST(Logging, Enumerations) +{ + using namespace Orthanc; + + Logging::LogCategory c; + ASSERT_TRUE(Logging::LookupCategory(c, "generic")); ASSERT_EQ(Logging::LogCategory_GENERIC, c); + ASSERT_TRUE(Logging::LookupCategory(c, "plugins")); ASSERT_EQ(Logging::LogCategory_PLUGINS, c); + ASSERT_TRUE(Logging::LookupCategory(c, "rest")); ASSERT_EQ(Logging::LogCategory_REST, c); + ASSERT_TRUE(Logging::LookupCategory(c, "sqlite")); ASSERT_EQ(Logging::LogCategory_SQLITE, c); + ASSERT_TRUE(Logging::LookupCategory(c, "dicom")); ASSERT_EQ(Logging::LogCategory_DICOM, c); + ASSERT_FALSE(Logging::LookupCategory(c, "nope")); + + ASSERT_EQ(5u, Logging::GetCategoriesCount()); + + std::set s; + for (size_t i = 0; i < Logging::GetCategoriesCount(); i++) + { + Logging::LogCategory c; + ASSERT_TRUE(Logging::LookupCategory(c, Logging::GetCategoryName(i))); + s.insert(Logging::GetCategoryName(i)); + } + + ASSERT_EQ(5u, s.size()); + ASSERT_NE(s.end(), s.find("generic")); + ASSERT_NE(s.end(), s.find("plugins")); + ASSERT_NE(s.end(), s.find("rest")); + ASSERT_NE(s.end(), s.find("sqlite")); + ASSERT_NE(s.end(), s.find("dicom")); + + ASSERT_THROW(Logging::GetCategoryName(Logging::GetCategoriesCount()), OrthancException); + + ASSERT_STREQ("generic", Logging::GetCategoryName(Logging::LogCategory_GENERIC)); + ASSERT_STREQ("plugins", Logging::GetCategoryName(Logging::LogCategory_PLUGINS)); + ASSERT_STREQ("rest", Logging::GetCategoryName(Logging::LogCategory_REST)); + ASSERT_STREQ("sqlite", Logging::GetCategoryName(Logging::LogCategory_SQLITE)); + ASSERT_STREQ("dicom", Logging::GetCategoryName(Logging::LogCategory_DICOM)); +} diff -r 09ed936fd381 -r d7a50b7b8466 OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp Tue Nov 03 12:28:25 2020 +0100 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestSystem.cpp Tue Nov 03 14:41:27 2020 +0100 @@ -42,6 +42,8 @@ #include "../OrthancInitialization.h" #include "../ServerContext.h" +#include + namespace Orthanc { @@ -511,6 +513,49 @@ } + static Logging::LogCategory GetCategory(const RestApiCall& call) + { + static const std::string PREFIX = "log-level-"; + + if (call.GetFullUri().size() == 2 && + call.GetFullUri() [0] == "tools" && + boost::starts_with(call.GetFullUri() [1], PREFIX)) + { + Logging::LogCategory category; + if (Logging::LookupCategory(category, call.GetFullUri() [1].substr(PREFIX.size()))) + { + return category; + } + } + + throw OrthancException(ErrorCode_InternalError); + } + + + static void GetLogLevelCategory(RestApiGetCall& call) + { + const std::string s = EnumerationToString(GetCategoryVerbosity(GetCategory(call))); + call.GetOutput().AnswerBuffer(s, MimeType_PlainText); + } + + + static void PutLogLevelCategory(RestApiPutCall& call) + { + std::string body; + call.BodyToString(body); + + Verbosity verbosity = StringToVerbosity(body); + Logging::LogCategory category = GetCategory(call); + SetCategoryVerbosity(category, verbosity); + + // Success + LOG(WARNING) << "REST API call has switched the log level of category \"" + << Logging::GetCategoryName(category) << "\" to \"" + << EnumerationToString(verbosity) << "\""; + call.GetOutput().AnswerBuffer("", MimeType_PlainText); + } + + void OrthancRestApi::RegisterSystem() { Register("/", ServeRoot); @@ -529,6 +574,13 @@ Register("/tools/log-level", GetLogLevel); Register("/tools/log-level", PutLogLevel); + for (size_t i = 0; i < Logging::GetCategoriesCount(); i++) + { + const std::string name(Logging::GetCategoryName(i)); + Register("/tools/log-level-" + name, GetLogLevelCategory); + Register("/tools/log-level-" + name, PutLogLevelCategory); + } + Register("/plugins", ListPlugins); Register("/plugins/{id}", GetPlugin); Register("/plugins/explorer.js", GetOrthancExplorerPlugins); diff -r 09ed936fd381 -r d7a50b7b8466 OrthancServer/UnitTestsSources/UnitTestsMain.cpp --- a/OrthancServer/UnitTestsSources/UnitTestsMain.cpp Tue Nov 03 12:28:25 2020 +0100 +++ b/OrthancServer/UnitTestsSources/UnitTestsMain.cpp Tue Nov 03 14:41:27 2020 +0100 @@ -131,24 +131,6 @@ ASSERT_STREQ("verbose", EnumerationToString(StringToVerbosity("verbose"))); ASSERT_STREQ("trace", EnumerationToString(StringToVerbosity("trace"))); ASSERT_THROW(StringToVerbosity("nope"), OrthancException); - - Logging::LogCategory c; - ASSERT_TRUE(Logging::LookupCategory(c, "generic")); ASSERT_EQ(Logging::LogCategory_GENERIC, c); - ASSERT_TRUE(Logging::LookupCategory(c, "plugins")); ASSERT_EQ(Logging::LogCategory_PLUGINS, c); - ASSERT_TRUE(Logging::LookupCategory(c, "rest")); ASSERT_EQ(Logging::LogCategory_REST, c); - ASSERT_TRUE(Logging::LookupCategory(c, "sqlite")); ASSERT_EQ(Logging::LogCategory_SQLITE, c); - ASSERT_TRUE(Logging::LookupCategory(c, "dicom")); ASSERT_EQ(Logging::LogCategory_DICOM, c); - ASSERT_FALSE(Logging::LookupCategory(c, "nope")); - - ASSERT_EQ(5u, Logging::GetCategoriesCount()); - - for (size_t i = 0; i < Logging::GetCategoriesCount(); i++) - { - Logging::LogCategory c; - ASSERT_TRUE(Logging::LookupCategory(c, Logging::GetCategoryName(i))); - } - - ASSERT_THROW(Logging::GetCategoryName(Logging::GetCategoriesCount()), OrthancException); }