Mercurial > hg > orthanc-object-storage
changeset 120:12ea59c97c40
sync orthanc folder + show timings + EnableAwsSdkLogs
author | Alain Mazy <am@osimis.io> |
---|---|
date | Tue, 21 Nov 2023 09:46:51 +0100 |
parents | ca68456d789a |
children | afea958425af |
files | Aws/AwsS3StoragePlugin.cpp Aws/CMakeLists.txt Azure/CMakeLists.txt Common/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Common/Resources/SyncOrthancFolder.py Common/StoragePlugin.cpp Google/CMakeLists.txt NEWS |
diffstat | 10 files changed, 140 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/Aws/AwsS3StoragePlugin.cpp Tue Oct 17 13:10:29 2023 +0200 +++ b/Aws/AwsS3StoragePlugin.cpp Tue Nov 21 09:46:51 2023 +0100 @@ -17,6 +17,7 @@ **/ #include "AwsS3StoragePlugin.h" +#include <Logging.h> #include <aws/core/Aws.h> #include <aws/s3/S3Client.h> @@ -26,6 +27,9 @@ #include <aws/s3/model/DeleteObjectRequest.h> #include <aws/core/auth/AWSCredentialsProvider.h> #include <aws/core/utils/HashingUtils.h> +#include <aws/core/utils/logging/DefaultLogSystem.h> +#include <aws/core/utils/logging/DefaultCRTLogSystem.h> +#include <aws/core/utils/logging/AWSLogging.h> #include <aws/core/utils/memory/stl/AWSStreamFwd.h> #include <aws/core/utils/memory/stl/AWSStringStream.h> #include <aws/core/utils/memory/AWSMemory.h> @@ -33,6 +37,7 @@ #include <aws/core/utils/StringUtils.h> #include <aws/transfer/TransferManager.h> #include <aws/crt/Api.h> +#include <iostream> #include <fstream> #include <boost/lexical_cast.hpp> @@ -378,6 +383,85 @@ static std::unique_ptr<Aws::Crt::ApiHandle> api_; static std::unique_ptr<Aws::SDKOptions> sdkOptions_; +#include <stdarg.h> + +class AwsOrthancLogger : public Aws::Utils::Logging::LogSystemInterface +{ +public: + virtual ~AwsOrthancLogger() {} + + /** + * Gets the currently configured log level for this logger. + */ + virtual Aws::Utils::Logging::LogLevel GetLogLevel() const + { + return Aws::Utils::Logging::LogLevel::Trace; + } + /** + * Does a printf style output to the output stream. Don't use this, it's unsafe. See LogStream + */ + virtual void Log(Aws::Utils::Logging::LogLevel logLevel, const char* tag, const char* formatStr, ...) + { + Aws::StringStream ss; + + va_list args; + va_start(args, formatStr); + + va_list tmp_args; //unfortunately you cannot consume a va_list twice + va_copy(tmp_args, args); //so we have to copy it + #ifdef _WIN32 + const int requiredLength = _vscprintf(formatStr, tmp_args) + 1; + #else + const int requiredLength = vsnprintf(nullptr, 0, formatStr, tmp_args) + 1; + #endif + va_end(tmp_args); + + char outputBuff[requiredLength]; + #ifdef _WIN32 + vsnprintf_s(outputBuff, requiredLength, _TRUNCATE, formatStr, args); + #else + vsnprintf(outputBuff, requiredLength, formatStr, args); + #endif // _WIN32 + + if (logLevel == Aws::Utils::Logging::LogLevel::Debug || logLevel == Aws::Utils::Logging::LogLevel::Trace) + { + LOG(INFO) << reinterpret_cast<const char*>(&outputBuff[0]); + } + else if (logLevel == Aws::Utils::Logging::LogLevel::Warn) + { + LOG(WARNING) << reinterpret_cast<const char*>(&outputBuff[0]); + } + else + { + LOG(ERROR) << reinterpret_cast<const char*>(&outputBuff[0]); + } + + va_end(args); + } + /** + * Writes the stream to the output stream. + */ + virtual void LogStream(Aws::Utils::Logging::LogLevel logLevel, const char* tag, const Aws::OStringStream &messageStream) + { + if (logLevel == Aws::Utils::Logging::LogLevel::Debug || logLevel == Aws::Utils::Logging::LogLevel::Trace) + { + LOG(INFO) << tag << messageStream.str(); + } + else if (logLevel == Aws::Utils::Logging::LogLevel::Warn) + { + LOG(WARNING) << tag << messageStream.str(); + } + else + { + LOG(ERROR) << tag << messageStream.str(); + } + + } + /** + * Writes any buffered messages to the underlying device if the logger supports buffering. + */ + virtual void Flush() {} +}; IStorage* AwsS3StoragePluginFactory::CreateStorage(const std::string& nameForLogs, const OrthancPlugins::OrthancConfiguration& orthancConfig) { @@ -386,14 +470,6 @@ throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls, "Cannot initialize twice"); } - api_.reset(new Aws::Crt::ApiHandle); - - sdkOptions_.reset(new Aws::SDKOptions); - sdkOptions_->cryptoOptions.initAndCleanupOpenSSL = false; // Done by the Orthanc framework - sdkOptions_->httpOptions.initAndCleanupCurl = false; // Done by the Orthanc framework - - Aws::InitAPI(*sdkOptions_); - bool enableLegacyStorageStructure; bool storageContainsUnknownFiles; @@ -432,8 +508,26 @@ const unsigned int connectTimeout = pluginSection.GetUnsignedIntegerValue("ConnectTimeout", 30); const unsigned int requestTimeout = pluginSection.GetUnsignedIntegerValue("RequestTimeout", 1200); const bool virtualAddressing = pluginSection.GetBooleanValue("VirtualAddressing", true); + const bool enableAwsSdkLogs = pluginSection.GetBooleanValue("EnableAwsSdkLogs", false); const std::string caFile = orthancConfig.GetStringValue("HttpsCACertificates", ""); - + + + api_.reset(new Aws::Crt::ApiHandle); + + sdkOptions_.reset(new Aws::SDKOptions); + sdkOptions_->cryptoOptions.initAndCleanupOpenSSL = false; // Done by the Orthanc framework + sdkOptions_->httpOptions.initAndCleanupCurl = false; // Done by the Orthanc framework + + if (enableAwsSdkLogs) + { + // Set up logging + Aws::Utils::Logging::InitializeAWSLogging(Aws::MakeShared<AwsOrthancLogger>(ALLOCATION_TAG)); + // strangely, this seems to disable logging !!!! sdkOptions_->loggingOptions.logLevel = Aws::Utils::Logging::LogLevel::Trace; + } + + Aws::InitAPI(*sdkOptions_); + + try { Aws::Client::ClientConfiguration configuration;
--- a/Aws/CMakeLists.txt Tue Oct 17 13:10:29 2023 +0200 +++ b/Aws/CMakeLists.txt Tue Nov 21 09:46:51 2023 +0100 @@ -19,13 +19,13 @@ project(OrthancAwsS3Storage) -set(PLUGIN_VERSION "mainline") +set(PLUGIN_VERSION "2.3.0") if (PLUGIN_VERSION STREQUAL "mainline") set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "mainline") set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "hg") else() - set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "1.12.1") + set(ORTHANC_FRAMEWORK_DEFAULT_VERSION "daf4807631c5") set(ORTHANC_FRAMEWORK_DEFAULT_SOURCE "web") endif()
--- a/Azure/CMakeLists.txt Tue Oct 17 13:10:29 2023 +0200 +++ b/Azure/CMakeLists.txt Tue Nov 21 09:46:51 2023 +0100 @@ -19,12 +19,13 @@ project(OrthancAzureBlobStorage) -set(PLUGIN_VERSION "mainline") +set(PLUGIN_VERSION "2.3.0") include(CheckIncludeFileCXX) -set(ORTHANC_FRAMEWORK_SOURCE "hg" CACHE STRING "orthanc source") -set(ORTHANC_FRAMEWORK_VERSION "mainline" CACHE STRING "orthanc framework version") # TODO: update to 1.12.2 when availableset(ALLOW_DOWNLOADS ON) +set(ORTHANC_FRAMEWORK_SOURCE "web" CACHE STRING "orthanc source") +set(ORTHANC_FRAMEWORK_VERSION "daf4807631c5" CACHE STRING "orthanc framework version") # TODO: update to 1.12.2 when available +set(ALLOW_DOWNLOADS ON) # Download and setup the Orthanc framework
--- a/Common/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Tue Oct 17 13:10:29 2023 +0200 +++ b/Common/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Tue Nov 21 09:46:51 2023 +0100 @@ -271,7 +271,7 @@ else() message("Forking the Orthanc source repository using Mercurial") execute_process( - COMMAND ${ORTHANC_FRAMEWORK_HG} clone "https://hg.orthanc-server.com/orthanc/" + COMMAND ${ORTHANC_FRAMEWORK_HG} clone "https://orthanc.uclouvain.be/hg/orthanc/" WORKING_DIRECTORY ${CMAKE_BINARY_DIR} RESULT_VARIABLE Failure )
--- a/Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Tue Oct 17 13:10:29 2023 +0200 +++ b/Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.cpp Tue Nov 21 09:46:51 2023 +0100 @@ -79,6 +79,10 @@ } } + void ResetGlobalContext() + { + globalContext_ = NULL; + } bool HasGlobalContext() {
--- a/Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Tue Oct 17 13:10:29 2023 +0200 +++ b/Common/Resources/Orthanc/Plugins/OrthancPluginCppWrapper.h Tue Nov 21 09:46:51 2023 +0100 @@ -137,6 +137,8 @@ void SetGlobalContext(OrthancPluginContext* context); + void ResetGlobalContext(); + bool HasGlobalContext(); OrthancPluginContext* GetGlobalContext();
--- a/Common/Resources/SyncOrthancFolder.py Tue Oct 17 13:10:29 2023 +0200 +++ b/Common/Resources/SyncOrthancFolder.py Tue Nov 21 09:46:51 2023 +0100 @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/python3 # # This maintenance script updates the content of the "Orthanc" folder @@ -8,11 +8,11 @@ import multiprocessing import os import stat -import urllib2 +import urllib.request TARGET = os.path.join(os.path.dirname(__file__), 'Orthanc') PLUGIN_SDK_VERSION = '1.12.1' -REPOSITORY = 'https://hg.orthanc-server.com/orthanc/raw-file' +REPOSITORY = 'https://orthanc.uclouvain.be/hg/orthanc/raw-file' FILES = [ ('OrthancFramework/Resources/CMake/AutoGeneratedCode.cmake', 'CMake'), @@ -42,7 +42,7 @@ branch = x[0] source = x[1] target = os.path.join(TARGET, x[2]) - print target + print(target) try: os.makedirs(os.path.dirname(target)) @@ -51,9 +51,9 @@ url = '%s/%s/%s' % (REPOSITORY, branch, source) - with open(target, 'w') as f: + with open(target, 'wb') as f: try: - f.write(urllib2.urlopen(url).read()) + f.write(urllib.request.urlopen(url).read()) except: print('ERROR %s' % url) raise
--- a/Common/StoragePlugin.cpp Tue Oct 17 13:10:29 2023 +0200 +++ b/Common/StoragePlugin.cpp Tue Nov 21 09:46:51 2023 +0100 @@ -88,6 +88,7 @@ { try { + Orthanc::Toolbox::ElapsedTimer timer; OrthancPlugins::LogInfo(primaryStorage->GetNameForLogs() + ": creating attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); std::unique_ptr<IStorage::IWriter> writer(primaryStorage->GetWriterForObject(uuid, type, cryptoEnabled)); @@ -111,6 +112,7 @@ { writer->Write(reinterpret_cast<const char*>(content), size); } + OrthancPlugins::LogInfo(primaryStorage->GetNameForLogs() + ": created attachment " + std::string(uuid) + " (" + timer.GetHumanTransferSpeed(true, size) + ")"); } catch (StoragePluginException& ex) { @@ -133,11 +135,13 @@ try { + Orthanc::Toolbox::ElapsedTimer timer; OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": reading range of attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); std::unique_ptr<IStorage::IReader> reader(storage->GetReaderForObject(uuid, type, cryptoEnabled)); reader->ReadRange(reinterpret_cast<char*>(target->data), target->size, rangeStart); + OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": read range of attachment " + std::string(uuid) + " (" + timer.GetHumanTransferSpeed(true, target->size) + ")"); return OrthancPluginErrorCode_Success; } catch (StoragePluginException& ex) @@ -181,6 +185,7 @@ { try { + Orthanc::Toolbox::ElapsedTimer timer; OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": reading whole attachment " + std::string(uuid) + " of type " + boost::lexical_cast<std::string>(type)); std::unique_ptr<IStorage::IReader> reader(storage->GetReaderForObject(uuid, type, cryptoEnabled)); @@ -227,6 +232,8 @@ { reader->ReadWhole(reinterpret_cast<char*>(target->data), fileSize); } + + OrthancPlugins::LogInfo(storage->GetNameForLogs() + ": read whole attachment " + std::string(uuid) + " (" + timer.GetHumanTransferSpeed(true, fileSize) + ")"); } catch (StoragePluginException& ex) {
--- a/Google/CMakeLists.txt Tue Oct 17 13:10:29 2023 +0200 +++ b/Google/CMakeLists.txt Tue Nov 21 09:46:51 2023 +0100 @@ -19,12 +19,12 @@ project(OrthancGoogleCloudStorage) -set(PLUGIN_VERSION "mainline") +set(PLUGIN_VERSION "2.3.0") include(CheckIncludeFileCXX) -set(ORTHANC_FRAMEWORK_SOURCE "hg" CACHE STRING "orthanc source") -set(ORTHANC_FRAMEWORK_VERSION "mainline" CACHE STRING "orthanc framework version") # TODO: update to 1.12.2 when available +set(ORTHANC_FRAMEWORK_SOURCE "web" CACHE STRING "orthanc source") +set(ORTHANC_FRAMEWORK_VERSION "daf4807631c5" CACHE STRING "orthanc framework version") # TODO: update to 1.12.2 when available set(ALLOW_DOWNLOADS ON) # Download and setup the Orthanc framework
--- a/NEWS Tue Oct 17 13:10:29 2023 +0200 +++ b/NEWS Tue Nov 21 09:46:51 2023 +0100 @@ -1,8 +1,15 @@ +Pending changes in the mainline +=============================== + +* AWS plugin: + * New configuration "EnableAwsSdkLogs" to include AWS SDK logs in Orthanc logs. +* Now displaying size, duration and transfer speed for each read/write operation. + 2023-10-17 - v 2.3.0 ==================== * AWS plugin: - * Added a new configuration "UseTransferMode" (false by default). + * Added a new configuration "UseTransferManager" (false by default). When set to true, the Transfer Manager mode is used to upload/download whole files to/from the bucket. If set to false, the default "object" mode is used. The Transfer Manager mode is supposed to be faster,