Mercurial > hg > orthanc
changeset 5575:d7eaa568da15
Orthanc::Logging automatically detects whether the Orthanc core supports OrthancPluginLogMessage()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 26 Apr 2024 17:17:34 +0200 |
parents | 823aae1ea72a |
children | 3a6d6d35193c |
files | OrthancFramework/Sources/Logging.cpp OrthancFramework/Sources/Logging.h OrthancFramework/Sources/Toolbox.cpp OrthancFramework/Sources/Toolbox.h OrthancFramework/UnitTestsSources/FrameworkTests.cpp OrthancServer/Plugins/Engine/OrthancPlugins.cpp OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h |
diffstat | 9 files changed, 309 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/OrthancFramework/Sources/Logging.cpp Fri Apr 26 16:01:26 2024 +0200 +++ b/OrthancFramework/Sources/Logging.cpp Fri Apr 26 17:17:34 2024 +0200 @@ -525,6 +525,7 @@ #include "Enumerations.h" #include "SystemToolbox.h" +#include "Toolbox.h" #include <fstream> #include <boost/filesystem.hpp> @@ -560,7 +561,8 @@ static boost::mutex loggingStreamsMutex_; static Orthanc::Logging::NullStream nullStream_; static OrthancPluginContext* pluginContext_ = NULL; // this is != NULL only when running from a plugin -static const char* pluginName_ = NULL; // this is != NULL only when running from a plugin +static std::string pluginName_; // this string can only be non-empty if running from a plugin +static bool hasOrthancAdvancedLogging_ = false; // Whether the Orthanc runtime is >= 1.12.4 static boost::recursive_mutex threadNamesMutex_; static std::map<boost::thread::id, std::string> threadNames_; static bool enableThreadNames_ = true; @@ -784,14 +786,23 @@ { assert(sizeof(_OrthancPluginService) == sizeof(int32_t)); + if (pluginContext == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + boost::mutex::scoped_lock lock(loggingStreamsMutex_); loggingStreamsContext_.reset(NULL); pluginContext_ = reinterpret_cast<OrthancPluginContext*>(pluginContext); + // The value "hasOrthancAdvancedLogging_" is cached to avoid computing it on every logged message + hasOrthancAdvancedLogging_ = Toolbox::IsVersionAbove(pluginContext_->orthancVersion, 1, 12, 4); + EnableInfoLevel(true); // allow the plugin to log at info level (but the Orthanc Core still decides of the level) } - void InitializePluginContext(void* pluginContext, const char* pluginName) + + void InitializePluginContext(void* pluginContext, const std::string& pluginName) { InitializePluginContext(pluginContext); pluginName_ = pluginName; @@ -983,14 +994,15 @@ if (pluginContext_ != NULL) { - if (pluginName_ != NULL) // this shall happen only if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4) && ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) + if (!pluginName_.empty() && + hasOrthancAdvancedLogging_) { _OrthancPluginLogMessage m; m.category = category_; m.level = level_; m.file = file_; m.line = line_; - m.plugin = pluginName_; + m.plugin = pluginName_.c_str(); m.message = message.c_str(); pluginContext_->InvokeService(pluginContext_, _OrthancPluginService_LogMessage, &m); }
--- a/OrthancFramework/Sources/Logging.h Fri Apr 26 16:01:26 2024 +0200 +++ b/OrthancFramework/Sources/Logging.h Fri Apr 26 17:17:34 2024 +0200 @@ -80,8 +80,8 @@ // "pluginContext" must be of type "OrthancPluginContext" ORTHANC_PUBLIC void InitializePluginContext(void* pluginContext); - // note: this variant shall be called only from a plugin and only if ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(1, 12, 4) && ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) - ORTHANC_PUBLIC void InitializePluginContext(void* pluginContext, const char* pluginName); + ORTHANC_PUBLIC void InitializePluginContext(void* pluginContext, + const std::string& pluginName); ORTHANC_PUBLIC void Initialize();
--- a/OrthancFramework/Sources/Toolbox.cpp Fri Apr 26 16:01:26 2024 +0200 +++ b/OrthancFramework/Sources/Toolbox.cpp Fri Apr 26 17:17:34 2024 +0200 @@ -2676,6 +2676,139 @@ } + bool Toolbox::ParseVersion(unsigned int& major, + unsigned int& minor, + unsigned int& revision, + const char* version) + { + if (version == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + +#ifdef _MSC_VER +#define ORTHANC_SCANF sscanf_s +#else +#define ORTHANC_SCANF sscanf +#endif + + int a, b, c; + if (ORTHANC_SCANF(version, "%4d.%4d.%4d", &a, &b, &c) == 3) + { + if (a >= 0 && + b >= 0 && + c >= 0) + { + major = static_cast<unsigned int>(a); + minor = static_cast<unsigned int>(b); + revision = static_cast<unsigned int>(c); + return true; + } + else + { + return false; + } + } + else if (ORTHANC_SCANF(version, "%4d.%4d", &a, &b) == 2) + { + if (a >= 0 && + b >= 0) + { + major = static_cast<unsigned int>(a); + minor = static_cast<unsigned int>(b); + revision = 0; + return true; + } + else + { + return false; + } + } + else if (ORTHANC_SCANF(version, "%4d", &a) == 1 && + a >= 0) + { + if (a >= 0) + { + major = static_cast<unsigned int>(a); + minor = 0; + revision = 0; + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + + + bool Toolbox::IsVersionAbove(const char* version, + unsigned int major, + unsigned int minor, + unsigned int revision) + { + /** + * Note: Similar standalone functions are implemented in + * "OrthancCPlugin.h" and "OrthancPluginCppWrapper.cpp". + **/ + + unsigned int actualMajor, actualMinor, actualRevision; + + if (version == NULL) + { + throw OrthancException(ErrorCode_NullPointer); + } + else if (!strcmp(version, "mainline")) + { + // Assume compatibility with the mainline + return true; + } + else if (ParseVersion(actualMajor, actualMinor, actualRevision, version)) + { + if (actualMajor > major) + { + return true; + } + + if (actualMajor < major) + { + return false; + } + + // Check the minor version number + assert(actualMajor == major); + + if (actualMinor > minor) + { + return true; + } + + if (actualMinor < minor) + { + return false; + } + + // Check the patch level version number + assert(actualMajor == major); + + if (actualRevision >= revision) + { + return true; + } + else + { + return false; + } + } + else + { + throw OrthancException(ErrorCode_ParameterOutOfRange, "Not a valid version: " + std::string(version)); + } + } }
--- a/OrthancFramework/Sources/Toolbox.h Fri Apr 26 16:01:26 2024 +0200 +++ b/OrthancFramework/Sources/Toolbox.h Fri Apr 26 17:17:34 2024 +0200 @@ -416,6 +416,15 @@ static std::string GetHumanTransferSpeed(bool full, uint64_t sizeInBytes, uint64_t durationInNanoseconds); + static bool ParseVersion(unsigned int& major, + unsigned int& minor, + unsigned int& revision, + const char* version); + + static bool IsVersionAbove(const char* version, + unsigned int major, + unsigned int minor, + unsigned int revision); }; }
--- a/OrthancFramework/UnitTestsSources/FrameworkTests.cpp Fri Apr 26 16:01:26 2024 +0200 +++ b/OrthancFramework/UnitTestsSources/FrameworkTests.cpp Fri Apr 26 17:17:34 2024 +0200 @@ -1602,3 +1602,53 @@ } } #endif + + +TEST(Toolbox, IsVersionAbove) +{ + unsigned int a, b, c; + ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "nope")); + ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "mainline")); + ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "")); + ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "-1")); + ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "1.-1")); + ASSERT_FALSE(Toolbox::ParseVersion(a, b, c, "1.1.-1")); + + ASSERT_TRUE(Toolbox::ParseVersion(a, b, c, "14.17.20")); + ASSERT_EQ(14u, a); + ASSERT_EQ(17u, b); + ASSERT_EQ(20u, c); + + ASSERT_TRUE(Toolbox::ParseVersion(a, b, c, "18.19")); + ASSERT_EQ(18u, a); + ASSERT_EQ(19u, b); + ASSERT_EQ(0u, c); + + ASSERT_TRUE(Toolbox::ParseVersion(a, b, c, "78")); + ASSERT_EQ(78u, a); + ASSERT_EQ(0u, b); + ASSERT_EQ(0u, c); + + ASSERT_TRUE(Toolbox::IsVersionAbove("mainline", 99, 99, 99)); + + ASSERT_TRUE(Toolbox::IsVersionAbove("18", 17, 99, 99)); + ASSERT_TRUE(Toolbox::IsVersionAbove("18", 18, 0, 0)); + ASSERT_FALSE(Toolbox::IsVersionAbove("18", 18, 0, 1)); + ASSERT_FALSE(Toolbox::IsVersionAbove("18", 18, 1, 0)); + ASSERT_FALSE(Toolbox::IsVersionAbove("18", 19, 0, 0)); + + ASSERT_TRUE(Toolbox::IsVersionAbove("18.19", 17, 99, 99)); + ASSERT_TRUE(Toolbox::IsVersionAbove("18.19", 18, 18, 99)); + ASSERT_TRUE(Toolbox::IsVersionAbove("18.19", 18, 19, 0)); + ASSERT_FALSE(Toolbox::IsVersionAbove("18.19", 18, 19, 1)); + ASSERT_FALSE(Toolbox::IsVersionAbove("18.19", 18, 20, 0)); + ASSERT_FALSE(Toolbox::IsVersionAbove("18.19", 19, 0, 0)); + + ASSERT_TRUE(Toolbox::IsVersionAbove("18.19.20", 17, 99, 99)); + ASSERT_TRUE(Toolbox::IsVersionAbove("18.19.20", 18, 18, 99)); + ASSERT_TRUE(Toolbox::IsVersionAbove("18.19.20", 18, 19, 19)); + ASSERT_TRUE(Toolbox::IsVersionAbove("18.19.20", 18, 19, 20)); + ASSERT_FALSE(Toolbox::IsVersionAbove("18.19.20", 18, 19, 21)); + ASSERT_FALSE(Toolbox::IsVersionAbove("18.19.20", 18, 20, 0)); + ASSERT_FALSE(Toolbox::IsVersionAbove("18.19.20", 19, 0, 0)); +}
--- a/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Fri Apr 26 16:01:26 2024 +0200 +++ b/OrthancServer/Plugins/Engine/OrthancPlugins.cpp Fri Apr 26 17:17:34 2024 +0200 @@ -2090,6 +2090,8 @@ sizeof(int32_t) != sizeof(OrthancPluginStorageCommitmentFailureReason) || sizeof(int32_t) != sizeof(OrthancPluginReceivedInstanceAction) || sizeof(int32_t) != sizeof(OrthancPluginLoadDicomInstanceMode) || + sizeof(int32_t) != sizeof(OrthancPluginLogLevel) || + sizeof(int32_t) != sizeof(OrthancPluginLogCategory) || static_cast<int>(OrthancPluginDicomToJsonFlags_IncludeBinary) != static_cast<int>(DicomToJsonFlags_IncludeBinary) || static_cast<int>(OrthancPluginDicomToJsonFlags_IncludePrivateTags) != static_cast<int>(DicomToJsonFlags_IncludePrivateTags) || static_cast<int>(OrthancPluginDicomToJsonFlags_IncludeUnknownTags) != static_cast<int>(DicomToJsonFlags_IncludeUnknownTags) ||
--- a/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Fri Apr 26 16:01:26 2024 +0200 +++ b/OrthancServer/Plugins/Include/orthanc/OrthancCPlugin.h Fri Apr 26 17:17:34 2024 +0200 @@ -1087,6 +1087,43 @@ /** + * The log levels supported by Orthanc. + * + * These values must match those of enumeration "LogLevel" in the + * Orthanc Core. + **/ + typedef enum + { + OrthancPluginLogLevel_Error = 0, /*!< Error log level */ + OrthancPluginLogLevel_Warning = 1, /*!< Warning log level */ + OrthancPluginLogLevel_Info = 2, /*!< Info log level */ + OrthancPluginLogLevel_Trace = 3, /*!< Trace log level */ + + _OrthancPluginLogLevel_INTERNAL = 0x7fffffff + } OrthancPluginLogLevel; + + + /** + * The log categories supported by Orthanc. + * + * These values must match those of enumeration "LogCategory" in the + * Orthanc Core. + **/ + typedef enum + { + OrthancPluginLogCategory_Generic = (1 << 0), /*!< Generic (default) category */ + OrthancPluginLogCategory_Plugins = (1 << 1), /*!< Plugin engine related logs (shall not be used by plugins) */ + OrthancPluginLogCategory_Http = (1 << 2), /*!< HTTP related logs */ + OrthancPluginLogCategory_Sqlite = (1 << 3), /*!< SQLite related logs (shall not be used by plugins) */ + OrthancPluginLogCategory_Dicom = (1 << 4), /*!< DICOM related logs */ + OrthancPluginLogCategory_Jobs = (1 << 5), /*!< jobs related logs */ + OrthancPluginLogCategory_Lua = (1 << 6), /*!< Lua related logs (shall not be used by plugins) */ + + _OrthancPluginLogCategory_INTERNAL = 0x7fffffff + } OrthancPluginLogCategory; + + + /** * @brief A 32-bit memory buffer allocated by the core system of Orthanc. * * A memory buffer allocated by the core system of Orthanc. When the @@ -1971,7 +2008,9 @@ sizeof(int32_t) != sizeof(OrthancPluginMetricsType) || sizeof(int32_t) != sizeof(OrthancPluginDicomWebBinaryMode) || sizeof(int32_t) != sizeof(OrthancPluginStorageCommitmentFailureReason) || - sizeof(int32_t) != sizeof(OrthancPluginLoadDicomInstanceMode)) + sizeof(int32_t) != sizeof(OrthancPluginLoadDicomInstanceMode) || + sizeof(int32_t) != sizeof(OrthancPluginLogLevel) || + sizeof(int32_t) != sizeof(OrthancPluginLogCategory)) { /* Mismatch in the size of the enumerations */ return 0; @@ -9480,37 +9519,10 @@ return context->InvokeService(context, _OrthancPluginService_SetCurrentThreadName, threadName); } - typedef enum - { - // these values must match LogLevel in the Orthanc Core - OrthancPluginLogLevel_Error = 0, /*!< Error log level */ - OrthancPluginLogLevel_Warning = 1, /*!< Warning log level */ - OrthancPluginLogLevel_Info = 2, /*!< Info log level */ - OrthancPluginLogLevel_Trace = 3, /*!< Trace log level */ - - // Force the enum to be 32 bits - OrthancPluginLogLevel_INTERNAL = 0x7FFFFFFF - } OrthancPluginLogLevel; - - typedef enum - { - // these values must match LogCategory in the Orthanc Core - OrthancPluginLogCategory_Generic = (1 << 0), /*!< Generic (default) category */ - OrthancPluginLogCategory_Plugins = (1 << 1), /*!< Plugin engine related logs (shall not be used by plugins) */ - OrthancPluginLogCategory_Http = (1 << 2), /*!< HTTP related logs */ - OrthancPluginLogCategory_Sqlite = (1 << 3), /*!< SQLite related logs (shall not be used by plugins) */ - OrthancPluginLogCategory_Dicom = (1 << 4), /*!< DICOM related logs */ - OrthancPluginLogCategory_Jobs = (1 << 5), /*!< jobs related logs */ - OrthancPluginLogCategory_Lua = (1 << 6), /*!< Lua related logs (shall not be used by plugins) */ - - // Force the enum to be 32 bits - OrthancPluginLogCategory_INTERNAL = 0x7FFFFFFF - } OrthancPluginLogCategory; - - - // note: this structure is also defined in Logging.h and it must be binary compatible + typedef struct { + /* Note: This structure is also defined in Logging.h and it must be binary compatible */ const char* message; const char* plugin; const char* file; @@ -9524,7 +9536,7 @@ * @brief Log a message. * * Log a message using the Orthanc logging system. - * + * * @param context The Orthanc plugin context, as received by OrthancPluginInitialize(). * @param message The message to be logged. * @param plugin The plugin name. @@ -9546,8 +9558,8 @@ m.message = message; m.plugin = plugin; m.file = file; + m.line = line; m.category = category; - m.line = line; m.level = level; context->InvokeService(context, _OrthancPluginService_LogMessage, &m); }
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Fri Apr 26 16:01:26 2024 +0200 +++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp Fri Apr 26 17:17:34 2024 +0200 @@ -113,6 +113,8 @@ } } + +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 void LogMessage(OrthancPluginLogLevel level, const char* file, uint32_t line, @@ -120,7 +122,7 @@ { if (HasGlobalContext()) { -#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 const char* pluginName = (pluginName_.empty() ? NULL : pluginName_.c_str()); OrthancPluginLogMessage(GetGlobalContext(), message.c_str(), pluginName, file, line, OrthancPluginLogCategory_Generic, level); #else @@ -144,6 +146,8 @@ #endif } } +#endif + void LogError(const std::string& message) {
--- a/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h Fri Apr 26 16:01:26 2024 +0200 +++ b/OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h Fri Apr 26 17:17:34 2024 +0200 @@ -53,6 +53,16 @@ #endif +#if !defined(ORTHANC_FRAMEWORK_VERSION_IS_ABOVE) +#define ORTHANC_FRAMEWORK_VERSION_IS_ABOVE(major, minor, revision) \ + (ORTHANC_VERSION_MAJOR > major || \ + (ORTHANC_VERSION_MAJOR == major && \ + (ORTHANC_VERSION_MINOR > minor || \ + (ORTHANC_VERSION_MINOR == minor && \ + ORTHANC_VERSION_REVISION >= revision)))) +#endif + + #if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 2, 0) // The "OrthancPluginFindMatcher()" primitive was introduced in Orthanc 1.2.0 # define HAS_ORTHANC_PLUGIN_FIND_MATCHER 1 @@ -117,16 +127,22 @@ # define HAS_ORTHANC_PLUGIN_WEBDAV 0 #endif +#if ORTHANC_PLUGINS_VERSION_IS_ABOVE(1, 12, 4) +# define HAS_ORTHANC_PLUGIN_LOG_MESSAGE 1 +#else +# define HAS_ORTHANC_PLUGIN_LOG_MESSAGE 0 +#endif -// Macro "ORTHANC_PLUGINS_DEPRECATED" tags a function as having been deprecated + +// Macro to tag a function as having been deprecated #if (__cplusplus >= 201402L) // C++14 -# define ORTHANC_PLUGINS_DEPRECATED(f) [[deprecated]] f +# define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) [[deprecated]] f #elif defined(__GNUC__) || defined(__clang__) -# define ORTHANC_PLUGINS_DEPRECATED(f) f __attribute__((deprecated)) +# define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) f __attribute__((deprecated)) #elif defined(_MSC_VER) -# define ORTHANC_PLUGINS_DEPRECATED(f) __declspec(deprecated) f +# define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(f) __declspec(deprecated) f #else -# define ORTHANC_PLUGINS_DEPRECATED +# define ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED #endif @@ -139,9 +155,16 @@ # define __ORTHANC_FILE__ __FILE__ #endif -#define ORTHANC_PLUGINS_LOG_ERROR(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Error, __ORTHANC_FILE__, __LINE__, msg); -#define ORTHANC_PLUGINS_LOG_WARNING(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Warning, __ORTHANC_FILE__, __LINE__, msg); -#define ORTHANC_PLUGINS_LOG_INFO(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Info, __ORTHANC_FILE__, __LINE__, msg); + +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 +# define ORTHANC_PLUGINS_LOG_ERROR(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Error, __ORTHANC_FILE__, __LINE__, msg) +# define ORTHANC_PLUGINS_LOG_WARNING(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Warning, __ORTHANC_FILE__, __LINE__, msg) +# define ORTHANC_PLUGINS_LOG_INFO(msg) ::OrthancPlugins::LogMessage(OrthancPluginLogLevel_Info, __ORTHANC_FILE__, __LINE__, msg) +#else +# define ORTHANC_PLUGINS_LOG_ERROR(msg) ::OrthancPlugins::LogError(msg) +# define ORTHANC_PLUGINS_LOG_WARNING(msg) ::OrthancPlugins::LogWarning(msg) +# define ORTHANC_PLUGINS_LOG_INFO(msg) ::OrthancPlugins::LogInfo(msg) +#endif namespace OrthancPlugins @@ -655,19 +678,33 @@ const char* AutodetectMimeType(const std::string& path); #endif +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 void LogMessage(OrthancPluginLogLevel level, const char* file, uint32_t line, const std::string& message); +#endif +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 // Use macro ORTHANC_PLUGINS_LOG_ERROR() instead - ORTHANC_PLUGINS_DEPRECATED(void LogError(const std::string& message)); + ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogError(const std::string& message)); +#else + void LogError(const std::string& message); +#endif +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 // Use macro ORTHANC_PLUGINS_LOG_WARNING() instead - ORTHANC_PLUGINS_DEPRECATED(void LogWarning(const std::string& message)); + ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogWarning(const std::string& message)); +#else + void LogWarning(const std::string& message); +#endif +#if HAS_ORTHANC_PLUGIN_LOG_MESSAGE == 1 // Use macro ORTHANC_PLUGINS_LOG_INFO() instead - ORTHANC_PLUGINS_DEPRECATED(void LogInfo(const std::string& message)); + ORTHANC_PLUGIN_CPP_WRAPPER_DEPRECATED(void LogInfo(const std::string& message)); +#else + void LogInfo(const std::string& message); +#endif void ReportMinimalOrthancVersion(unsigned int major, unsigned int minor,