diff --git a/Framework/API/inc/MantidAPI/FrameworkManager.h b/Framework/API/inc/MantidAPI/FrameworkManager.h index 8d3bab5c249ddf2de8e3ae7a71a40e3bffeca408..23948cfcee574acc147e078fbb33683d5b087072 100644 --- a/Framework/API/inc/MantidAPI/FrameworkManager.h +++ b/Framework/API/inc/MantidAPI/FrameworkManager.h @@ -76,7 +76,7 @@ public: /// Clear memory associated with the PropertyManagers void clearPropertyManagers(); - + void shutdown(); /// Creates and instance of an algorithm IAlgorithm *createAlgorithm(const std::string &algName, const int &version = -1); @@ -100,7 +100,6 @@ public: /// Deletes a workspace from the framework bool deleteWorkspace(const std::string &wsName); - private: friend struct Mantid::Kernel::CreateUsingNew<FrameworkManagerImpl>; @@ -119,6 +118,8 @@ private: void disableNexusOutput(); /// Starts asynchronous tasks that are done as part of Start-up void AsynchronousStartupTasks(); + /// Setup Usage Reporting if enabled + void setupUsageReporting(); /// Update instrument definitions from github void UpdateInstrumentDefinitions(); /// check if a newer version of Mantid is available diff --git a/Framework/API/src/Algorithm.cpp b/Framework/API/src/Algorithm.cpp index f874d0a01265367a2fc8532c6b4361cb91980441..e42eb6d80a8dc566202849e563dff37ed87b33e4 100644 --- a/Framework/API/src/Algorithm.cpp +++ b/Framework/API/src/Algorithm.cpp @@ -17,7 +17,7 @@ #include "MantidKernel/MultiThreaded.h" #include "MantidKernel/Strings.h" #include "MantidKernel/Timer.h" -#include "MantidKernel/UsageReporter.h" +#include "MantidKernel/UsageService.h" #include <boost/algorithm/string/regex.hpp> #include <boost/weak_ptr.hpp> @@ -1582,20 +1582,20 @@ void Algorithm::reportCompleted(const double &duration, */ void Algorithm::registerFeatureUsage(const float &duration) const { - if (ConfigService::Instance().UsageReporter().isEnabled()) { + if (UsageService::Instance().isEnabled()) { ::Json::FastWriter writer; ::Json::Value algJson = toJson(); algJson["internal"] = isChild(); std::string details = writer.write(algJson); //Limit details length for very long strings - const int STRING_SIZE_LIMIT = 60000; + const int STRING_SIZE_LIMIT = 8000; if (details.size() > STRING_SIZE_LIMIT) details.erase(STRING_SIZE_LIMIT, std::string::npos); std::ostringstream oss; oss << this->name() << ".v" << this->version(); - ConfigService::Instance().UsageReporter().registerFeatureUsage("Algorithm", oss.str(), + UsageService::Instance().registerFeatureUsage("Algorithm", oss.str(), DateAndTime::getCurrentTime(), duration, details); } diff --git a/Framework/API/src/FrameworkManager.cpp b/Framework/API/src/FrameworkManager.cpp index 90f6287cb0a6e6949479285aff80dd36474cc34a..e933fc64a6c9000d5a5dd5eb995a9501829248ee 100644 --- a/Framework/API/src/FrameworkManager.cpp +++ b/Framework/API/src/FrameworkManager.cpp @@ -8,7 +8,7 @@ #include "MantidAPI/MemoryManager.h" #include "MantidAPI/PropertyManagerDataService.h" #include "MantidAPI/WorkspaceGroup.h" -#include "MantidAPI/UsageService.h" +#include "MantidKernel/UsageService.h" #include "MantidKernel/Exception.h" #include "MantidKernel/LibraryManager.h" @@ -113,7 +113,7 @@ void FrameworkManagerImpl::AsynchronousStartupTasks() { g_log.information() << "Version check disabled." << std::endl; } - UsageService::Instance().registerStartup(); + setupUsageReporting(); } /// Update instrument definitions from github @@ -250,6 +250,12 @@ void FrameworkManagerImpl::clearPropertyManagers() { PropertyManagerDataService::Instance().clear(); } +void FrameworkManagerImpl::shutdown() { + //clear(); + Kernel::UsageService::Instance().shutdown(); +} + + /** Creates and initialises an instance of an algorithm * * @param algName :: The name of the algorithm required @@ -411,5 +417,17 @@ bool FrameworkManagerImpl::deleteWorkspace(const std::string &wsName) { return retVal; } +void FrameworkManagerImpl::setupUsageReporting() { + int enabled = 0; + int interval = 0; + int retVal = Kernel::ConfigService::Instance().getValue("Usage.BufferCheckInterval", interval); + if ((retVal == 1) && (interval > 0)) { + Kernel::UsageService::Instance().setInterval(interval); + } + retVal = Kernel::ConfigService::Instance().getValue("usagereports.enabled", enabled); + Kernel::UsageService::Instance().setEnabled((retVal == 0) || (enabled == 0)); + Kernel::UsageService::Instance().registerStartup(); +} + } // namespace API } // Namespace Mantid diff --git a/Framework/Kernel/CMakeLists.txt b/Framework/Kernel/CMakeLists.txt index eb1a3cefa2831762736c9626e01eb8e97caa7f75..c0fc7be3921f100140203c267d6586c6957b2dc8 100644 --- a/Framework/Kernel/CMakeLists.txt +++ b/Framework/Kernel/CMakeLists.txt @@ -102,7 +102,7 @@ set ( SRC_FILES src/UnitFactory.cpp src/UnitLabel.cpp src/UnitLabelTypes.cpp - src/UsageReporter.cpp + src/UsageService.cpp src/UserCatalogInfo.cpp src/UserStringParser.cpp src/Utils.cpp @@ -262,7 +262,7 @@ set ( INC_FILES inc/MantidKernel/UnitFactory.h inc/MantidKernel/UnitLabel.h inc/MantidKernel/UnitLabelTypes.h - inc/MantidKernel/UsageReporter.h + inc/MantidKernel/UsageService.h inc/MantidKernel/UserCatalogInfo.h inc/MantidKernel/UserStringParser.h inc/MantidKernel/Utils.h @@ -384,7 +384,7 @@ set ( TEST_FILES UnitFactoryTest.h UnitLabelTest.h UnitTest.h - UsageReporterTest.h + UsageServiceTest.h UserCatalogInfoTest.h UserStringParserTest.h UtilsTest.h diff --git a/Framework/Kernel/inc/MantidKernel/ConfigService.h b/Framework/Kernel/inc/MantidKernel/ConfigService.h index 753fbe0c860266e762937f2d3926f51eaeacf1d3..f1776bb1c28b2a151b59e4d1986a59db63ff3fd5 100644 --- a/Framework/Kernel/inc/MantidKernel/ConfigService.h +++ b/Framework/Kernel/inc/MantidKernel/ConfigService.h @@ -255,15 +255,11 @@ public: /// Gets the proxy for the system Kernel::ProxyInfo &getProxy(const std::string &url); - /// Gets access to the UsageReporter - Mantid::Kernel::UsageReporter& UsageReporter(); - private: friend struct Mantid::Kernel::CreateUsingNew<ConfigServiceImpl>; /// Handles distribution of Poco signals. mutable Poco::NotificationCenter m_notificationCenter; - void setupUsageReporting(); // Private constructors and destructor for singleton class ConfigServiceImpl(); /// Private copy constructor. Prevents singleton being copied. @@ -344,10 +340,8 @@ private: /// local cache of proxy details Kernel::ProxyInfo m_proxyInfo; - /// wether the proxy has been populated yet + /// whether the proxy has been populated yet bool m_isProxySet; - ///Usage Reporter - Mantid::Kernel::UsageReporter *m_usage_reporter; }; /// Forward declaration of a specialisation of SingletonHolder for diff --git a/Framework/Kernel/inc/MantidKernel/UsageReporter.h b/Framework/Kernel/inc/MantidKernel/UsageService.h similarity index 84% rename from Framework/Kernel/inc/MantidKernel/UsageReporter.h rename to Framework/Kernel/inc/MantidKernel/UsageService.h index 57f0d7ff9b5a427384f0dd84be0d11a1badd3125..6f28354cebf7f01ae73c6741157f796b947c3b77 100644 --- a/Framework/Kernel/inc/MantidKernel/UsageReporter.h +++ b/Framework/Kernel/inc/MantidKernel/UsageService.h @@ -1,9 +1,10 @@ -#ifndef MANTID_KERNEL_USAGEREPORTER_H_ -#define MANTID_KERNEL_USAGEREPORTER_H_ +#ifndef MANTID_KERNEL_USAGESERVICE_H_ +#define MANTID_KERNEL_USAGESERVICE_H_ #include "MantidKernel/DllConfig.h" #include "MantidKernel/DateAndTime.h" #include "MantidKernel/MultiThreaded.h" +#include "MantidKernel/SingletonHolder.h" #include <json/value.h> @@ -64,7 +65,7 @@ public: std::string details; }; -class MANTID_KERNEL_DLL UsageReporter { +class MANTID_KERNEL_DLL UsageServiceImpl { public: /// Sets the interval that the timer checks for tasks void setInterval(const uint32_t seconds = 60); @@ -84,17 +85,19 @@ public: /// flushes any buffers and sends any outstanding usage reports void flush(); + void shutdown(); - /// Constructor - UsageReporter(); - /// Destructor - ~UsageReporter(); private: + friend struct Mantid::Kernel::CreateUsingNew<UsageServiceImpl>; /// Private, unimplemented copy constructor - UsageReporter(const UsageReporter &); + UsageServiceImpl(const UsageServiceImpl &); /// Private, unimplemented copy assignment operator - UsageReporter &operator=(const UsageReporter &); - + UsageServiceImpl &operator=(const UsageServiceImpl &); + /// Constructor + UsageServiceImpl(); + /// Destructor + ~UsageServiceImpl(); + /// Send startup Report void sendStartupReport(); /// Send featureUsageReport @@ -130,7 +133,18 @@ private: ::Json::Value m_cachedHeader; }; +/// Forward declaration of a specialisation of SingletonHolder for +/// AlgorithmFactoryImpl (needed for dllexport/dllimport) and a typedef for it. +#if defined(__APPLE__) && defined(__INTEL_COMPILER) +inline +#endif +template class MANTID_KERNEL_DLL +Mantid::Kernel::SingletonHolder<UsageServiceImpl>; +typedef MANTID_KERNEL_DLL Mantid::Kernel::SingletonHolder<UsageServiceImpl> +UsageService; + + } // namespace API } // namespace Mantid -#endif /* MANTID_KERNEL_USAGEREPORTER_H_ */ \ No newline at end of file +#endif /* MANTID_KERNEL_USAGESERVICE_H_ */ \ No newline at end of file diff --git a/Framework/Kernel/src/ConfigService.cpp b/Framework/Kernel/src/ConfigService.cpp index e994fb3557ab0f863f37c8b2f1359c3760954917..e27259770167d892cacf1973e9369b64bb6a0ff6 100644 --- a/Framework/Kernel/src/ConfigService.cpp +++ b/Framework/Kernel/src/ConfigService.cpp @@ -11,7 +11,6 @@ #include "MantidKernel/Exception.h" #include "MantidKernel/FacilityInfo.h" #include "MantidKernel/NetworkProxy.h" -#include "MantidKernel/UsageReporter.h" #include <Poco/Util/LoggingConfigurator.h> #include <Poco/Util/SystemConfiguration.h> @@ -140,20 +139,6 @@ private: // Private member functions //------------------------------- -void ConfigServiceImpl::setupUsageReporting() { - m_usage_reporter = new Mantid::Kernel::UsageReporter(); - - int enabled = 0; - int interval = 0; - int retVal = getValue("Usage.BufferCheckInterval", interval); - if ((retVal == 1) && (interval > 0)) { - m_usage_reporter->setInterval(interval); - } - retVal = getValue("usagereports.enabled", enabled); - m_usage_reporter->setEnabled((retVal == 0) || (enabled == 0)); - m_usage_reporter->registerStartup(); -} - /// Private constructor for singleton class ConfigServiceImpl::ConfigServiceImpl() : m_pConf(NULL), m_pSysConfig(NULL), m_changed_keys(), m_ConfigPaths(), @@ -167,8 +152,7 @@ ConfigServiceImpl::ConfigServiceImpl() m_user_properties_file_name("Mantid.user.properties"), #endif m_DataSearchDirs(), m_UserSearchDirs(), m_InstrumentDirs(), - m_instr_prefixes(), m_proxyInfo(), m_isProxySet(false), - m_usage_reporter(NULL) { + m_instr_prefixes(), m_proxyInfo(), m_isProxySet(false) { // getting at system details m_pSysConfig = new WrappedObject<Poco::Util::SystemConfiguration>; m_pConf = 0; @@ -294,17 +278,12 @@ ConfigServiceImpl::ConfigServiceImpl() } // must update the cache of instrument paths cacheInstrumentPaths(); - - // setup usage reporting - setupUsageReporting(); } /** Private Destructor * Prevents client from calling 'delete' on the pointer handed out by Instance */ ConfigServiceImpl::~ConfigServiceImpl() { - //clear up the usage reporter first - delete m_usage_reporter; // std::cerr << "ConfigService destroyed." << std::endl; Kernel::Logger::shutdown(); delete m_pSysConfig; @@ -1986,13 +1965,6 @@ Kernel::ProxyInfo &ConfigServiceImpl::getProxy(const std::string &url) { return m_proxyInfo; } -/** Gets a reference to the UsageReporter -* @returns a reference to the UsageReporter class -*/ -UsageReporter& ConfigServiceImpl::UsageReporter() -{ - return *m_usage_reporter; -} /** Sets the log level priority for the File log channel * @param logLevel the integer value of the log level to set, 1=Critical, 7=Debug diff --git a/Framework/Kernel/src/UsageReporter.cpp b/Framework/Kernel/src/UsageService.cpp similarity index 78% rename from Framework/Kernel/src/UsageReporter.cpp rename to Framework/Kernel/src/UsageService.cpp index 9b847b1ba73146cac622736fbf880ec854da7854..c7855e8e8effaff1fbd6abc24b1a51f530bf7f09 100644 --- a/Framework/Kernel/src/UsageReporter.cpp +++ b/Framework/Kernel/src/UsageService.cpp @@ -1,4 +1,4 @@ -#include "MantidKernel/UsageReporter.h" +#include "MantidKernel/UsageService.h" #include "MantidKernel/ChecksumHelper.h" #include "MantidKernel/ConfigService.h" #include "MantidKernel/DateAndTime.h" @@ -16,12 +16,12 @@ namespace Mantid { namespace Kernel { /// static logger -Kernel::Logger g_log("UsageReporter"); +Kernel::Logger g_log("UsageServiceImpl"); // const std::string STARTUP_URL("http://reports.mantidproject.org/api/usage"); const std::string STARTUP_URL( "http://posttestserver.com/post.php?dir=Mantid"); // dev location - // http://posttestserver.com/data/ +// http://posttestserver.com/data/ // const std::string FEATURE_URL("http://reports.mantidproject.org/api/usage"); const std::string FEATURE_URL( "http://posttestserver.com/post.php?dir=Mantid"); // dev location @@ -52,9 +52,9 @@ std::string FeatureUsage::asString() const { } //---------------------------------------------------------------------------------------------- -/** Constructor for UsageReporter +/** Constructor for UsageServiceImpl */ -UsageReporter::UsageReporter() +UsageServiceImpl::UsageServiceImpl() : m_timer(), m_timerTicks(0), m_timerTicksTarget(0), m_FeatureQueue(), m_FeatureQueueSizeThreshold(50), m_isEnabled(false), m_mutex(), m_cachedHeader() { @@ -64,33 +64,20 @@ UsageReporter::UsageReporter() //---------------------------------------------------------------------------------------------- /** Destructor */ -UsageReporter::~UsageReporter() { - try { - try { - // stop the timer - m_timer.restart(0); - // send any remaining feature usage records - flush(); - } catch (std::exception &ex) { - g_log.error() << "Error during the closedown of the UsageService. " - << ex.what(); - } - } catch (...) { // do not allow exceptions to leave the destructor - } -} +UsageServiceImpl::~UsageServiceImpl() {} -void UsageReporter::setInterval(const uint32_t seconds) { +void UsageServiceImpl::setInterval(const uint32_t seconds) { // set the ticks target to by 24 hours / interval m_timerTicksTarget = 24 * 60 * 60 / seconds; m_timer.setPeriodicInterval((seconds * 1000)); if (isEnabled()) { - m_timer.start(Poco::TimerCallback<UsageReporter>( - *this, &UsageReporter::timerCallback)); + m_timer.start(Poco::TimerCallback<UsageServiceImpl>( + *this, &UsageServiceImpl::timerCallback)); } } -void UsageReporter::registerStartup() { +void UsageServiceImpl::registerStartup() { if (isEnabled()) { sendStartupReport(); } @@ -99,7 +86,7 @@ void UsageReporter::registerStartup() { //---------------------------------------------------------------------------------------------- /** registerFeatureUsage Overloads */ -void UsageReporter::registerFeatureUsage(const std::string &type, +void UsageServiceImpl::registerFeatureUsage(const std::string &type, const std::string &name, const Kernel::DateAndTime &start, const float &duration, @@ -107,7 +94,7 @@ void UsageReporter::registerFeatureUsage(const std::string &type, m_FeatureQueue.push(FeatureUsage(type, name, start, duration, details)); } -void UsageReporter::registerFeatureUsage(const std::string &type, +void UsageServiceImpl::registerFeatureUsage(const std::string &type, const std::string &name, const std::string &details) { registerFeatureUsage(type, name, DateAndTime::getCurrentTime(), 0.0, details); @@ -115,13 +102,13 @@ void UsageReporter::registerFeatureUsage(const std::string &type, //---------------------------------------------------------------------------------------------- -bool UsageReporter::isEnabled() const { return m_isEnabled; } +bool UsageServiceImpl::isEnabled() const { return m_isEnabled; } -void UsageReporter::setEnabled(const bool enabled) { +void UsageServiceImpl::setEnabled(const bool enabled) { if (m_isEnabled != enabled) { if (enabled) { - m_timer.start(Poco::TimerCallback<UsageReporter>( - *this, &UsageReporter::timerCallback)); + m_timer.start(Poco::TimerCallback<UsageServiceImpl>( + *this, &UsageServiceImpl::timerCallback)); } else { m_timer.stop(); } @@ -129,13 +116,25 @@ void UsageReporter::setEnabled(const bool enabled) { m_isEnabled = enabled; } -void UsageReporter::flush() { +void UsageServiceImpl::flush() { if (isEnabled()) { sendFeatureUsageReport(true); } } -void UsageReporter::sendStartupReport() { +void UsageServiceImpl::shutdown() { + try { + // stop the timer + setEnabled(false); + // send any remaining feature usage records + sendFeatureUsageReport(true); + } catch (std::exception &ex) { + g_log.error() << "Error during the shutdown of the UsageService. " + << ex.what(); + } +} + +void UsageServiceImpl::sendStartupReport() { try { std::string message = this->generateStartupMessage(); @@ -147,10 +146,10 @@ void UsageReporter::sendStartupReport() { } } -void UsageReporter::sendFeatureUsageReport(const bool synchronous = false) { +void UsageServiceImpl::sendFeatureUsageReport(const bool synchronous = false) { try { std::string message = this->generateFeatureUsageMessage(); - //g_log.debug() << "FeatureUsage to send\n" << message << std::endl; + // g_log.debug() << "FeatureUsage to send\n" << message << std::endl; if (!message.empty()) { if (synchronous) { sendFeatureAsyncImpl(message); @@ -165,7 +164,7 @@ void UsageReporter::sendFeatureUsageReport(const bool synchronous = false) { } } -void UsageReporter::timerCallback(Poco::Timer &) { +void UsageServiceImpl::timerCallback(Poco::Timer &) { m_timerTicks++; if (m_timerTicks > m_timerTicksTarget) { // send startup report @@ -182,7 +181,7 @@ void UsageReporter::timerCallback(Poco::Timer &) { /** * This puts together the system information for the json document. */ -::Json::Value UsageReporter::generateHeader() { +::Json::Value UsageServiceImpl::generateHeader() { ::Json::Value header = m_cachedHeader; if (header.size() == 0) { @@ -220,7 +219,7 @@ void UsageReporter::timerCallback(Poco::Timer &) { return header; } -std::string UsageReporter::generateStartupMessage() { +std::string UsageServiceImpl::generateStartupMessage() { auto message = this->generateHeader(); // get the properties that were set# @@ -234,7 +233,7 @@ std::string UsageReporter::generateStartupMessage() { return writer.write(message); } -std::string UsageReporter::generateFeatureUsageMessage() { +std::string UsageServiceImpl::generateFeatureUsageMessage() { auto message = this->generateHeader(); ::Json::FastWriter writer; @@ -265,34 +264,34 @@ std::string UsageReporter::generateFeatureUsageMessage() { * Asynchronous execution */ Poco::ActiveResult<int> -UsageReporter::sendStartupAsync(const std::string &message) { - auto sendAsync = new Poco::ActiveMethod<int, std::string, UsageReporter>( - this, &UsageReporter::sendStartupAsyncImpl); +UsageServiceImpl::sendStartupAsync(const std::string &message) { + auto sendAsync = new Poco::ActiveMethod<int, std::string, UsageServiceImpl>( + this, &UsageServiceImpl::sendStartupAsyncImpl); return (*sendAsync)(message); } /**Async method for sending startup messages */ -int UsageReporter::sendStartupAsyncImpl(const std::string &message) { +int UsageServiceImpl::sendStartupAsyncImpl(const std::string &message) { return this->sendReport(message, STARTUP_URL); } /**Async method for sending feature messages */ Poco::ActiveResult<int> -UsageReporter::sendFeatureAsync(const std::string &message) { - auto sendAsync = new Poco::ActiveMethod<int, std::string, UsageReporter>( - this, &UsageReporter::sendFeatureAsyncImpl); +UsageServiceImpl::sendFeatureAsync(const std::string &message) { + auto sendAsync = new Poco::ActiveMethod<int, std::string, UsageServiceImpl>( + this, &UsageServiceImpl::sendFeatureAsyncImpl); return (*sendAsync)(message); } /**Async method for sending feature messages */ -int UsageReporter::sendFeatureAsyncImpl(const std::string &message) { +int UsageServiceImpl::sendFeatureAsyncImpl(const std::string &message) { return this->sendReport(message, FEATURE_URL); } -int UsageReporter::sendReport(const std::string &message, +int UsageServiceImpl::sendReport(const std::string &message, const std::string &url) { int status = -1; try { diff --git a/Framework/Kernel/test/UsageReporterTest.h b/Framework/Kernel/test/UsageServiceTest.h similarity index 88% rename from Framework/Kernel/test/UsageReporterTest.h rename to Framework/Kernel/test/UsageServiceTest.h index db018867748cb8a55486171589654949359962b0..0b4cef2ca801df46a90d5be3daf007631c7fd6c5 100644 --- a/Framework/Kernel/test/UsageReporterTest.h +++ b/Framework/Kernel/test/UsageServiceTest.h @@ -3,9 +3,9 @@ #include <cxxtest/TestSuite.h> -#include "MantidKernel/UsageReporter.h" +#include "MantidKernel/UsageService.h" -using Mantid::Kernel::UsageReporter; +using Mantid::Kernel::UsageServiceImpl; class UsageServiceTest : public CxxTest::TestSuite { public: