Mercurial > hg > orthanc
changeset 3359:815b81142ff7 emscripten-logging
Enable custom logging functions to redirect to emscripten specific logging calls
in the ORTHANC_ENABLE_LOGGING_STDIO mode.
author | Benjamin Golinvaux <bgo@osimis.io> |
---|---|
date | Tue, 07 May 2019 11:23:11 +0200 |
parents | eb18269de57f |
children | ea07b29c6d0e |
files | Core/Logging.cpp Core/Logging.h Core/LoggingUtils.h LinuxCompilation.txt UnitTestsSources/LoggingTests.cpp |
diffstat | 5 files changed, 196 insertions(+), 80 deletions(-) [+] |
line wrap: on
line diff
--- a/Core/Logging.cpp Wed Apr 24 07:51:48 2019 +0200 +++ b/Core/Logging.cpp Tue May 07 11:23:11 2019 +0200 @@ -63,7 +63,17 @@ void EnableTraceLevel(bool enabled) { } + + bool IsTraceLevelEnabled() + { + return false; + } + bool IsInfoLevelEnabled() + { + return false; + } + void SetTargetFile(const std::string& path) { } @@ -140,12 +150,18 @@ #elif ORTHANC_ENABLE_LOGGING_STDIO == 1 /********************************************************* - * Logger compatible with <stdio.h> + * Logger compatible with <stdio.h> OR logger that sends its + * output to the emscripten html5 api (depending on the + * definition of __EMSCRIPTEN__) *********************************************************/ #include <stdio.h> #include <boost/lexical_cast.hpp> +#ifdef __EMSCRIPTEN__ +#include "emscripten/html5.h" +#endif + namespace Orthanc { namespace Logging @@ -153,6 +169,67 @@ static bool globalVerbose_ = false; static bool globalTrace_ = false; +#ifdef __EMSCRIPTEN__ + void defaultErrorLogFunc(const char* msg) + { + emscripten_console_error(msg); + } + + void defaultWarningLogFunc(const char* msg) + { + emscripten_console_warn(msg); + } + + void defaultInfoLogFunc(const char* msg) + { + emscripten_console_log(msg); + } + + void defaultTraceLogFunc(const char* msg) + { + emscripten_console_log(msg); + } +#else +// __EMSCRIPTEN__ not #defined + void defaultErrorLogFunc(const char* msg) + { + fprintf(stderr, "E: %s\n", msg); + } + + void defaultWarningLogFunc(const char*) + { + fprintf(stdout, "W: %s\n", msg); + } + + void defaultInfoLogFunc(const char*) + { + fprintf(stdout, "I: %s\n", msg); + } + + void defaultTraceLogFunc(const char*) + { + fprintf(stdout, "T: %s\n", msg); + } +#endif +// __EMSCRIPTEN__ + + static LoggingFunction globalErrorLogFunc = defaultErrorLogFunc; + static LoggingFunction globalWarningLogFunc = defaultWarningLogFunc; + static LoggingFunction globalInfoLogFunc = defaultInfoLogFunc; + static LoggingFunction globalTraceLogFunc = defaultTraceLogFunc; + + void SetErrorWarnInfoTraceLoggingFunctions( + LoggingFunction errorLogFunc, + LoggingFunction warningLogfunc, + LoggingFunction infoLogFunc, + LoggingFunction traceLogFunc) + { + globalErrorLogFunc = errorLogFunc; + globalWarningLogFunc = warningLogfunc; + globalInfoLogFunc = infoLogFunc; + globalTraceLogFunc = traceLogFunc; + } + InternalLogger::InternalLogger(InternalLevel level, const char* file /* ignored */, int line /* ignored */) : @@ -165,29 +242,35 @@ switch (level_) { case InternalLevel_ERROR: - fprintf(stderr, "E: %s\n", message_.c_str()); + globalErrorLogFunc(message_.c_str()); break; case InternalLevel_WARNING: - fprintf(stdout, "W: %s\n", message_.c_str()); + globalWarningLogFunc(message_.c_str()); break; case InternalLevel_INFO: if (globalVerbose_) { - fprintf(stdout, "I: %s\n", message_.c_str()); + globalInfoLogFunc(message_.c_str()); + // TODO: stone_console_info(message_.c_str()); } break; case InternalLevel_TRACE: if (globalTrace_) { - fprintf(stdout, "T: %s\n", message_.c_str()); + globalTraceLogFunc(message_.c_str()); } break; default: - fprintf(stderr, "Unknown log level (%d) for message: %s\n", level_, message_.c_str()); + { + std::stringstream ss; + ss << "Unknown log level (" << level_ << ") for message: " << message_; + auto s = ss.str(); + globalErrorLogFunc(s.c_str()); + } } } @@ -196,10 +279,21 @@ globalVerbose_ = enabled; } + bool IsInfoLevelEnabled() + { + return globalVerbose_; + } + void EnableTraceLevel(bool enabled) { globalTrace_ = enabled; } + + bool IsTraceLevelEnabled() + { + return globalTrace_; + } + } } @@ -388,7 +482,7 @@ { LoggingMementoImpl* memento = new LoggingMementoImpl(); - memento->valid_ = TRUE; + memento->valid_ = true; { boost::mutex::scoped_lock lock(loggingMutex_); memento->infoEnabled_ = loggingContext_->infoEnabled_; @@ -409,7 +503,7 @@ reinterpret_cast<LoggingMementoImpl*>(mementoPtr); if (!memento->valid_) throw std::runtime_error("Memento already used"); - memento->valid_ = FALSE; + memento->valid_ = false; { boost::mutex::scoped_lock lock(loggingMutex_); loggingContext_.reset(new LoggingContext); @@ -450,6 +544,14 @@ } } + bool IsInfoLevelEnable() + { + boost::mutex::scoped_lock lock(loggingMutex_); + assert(loggingContext_.get() != NULL); + + return loggingContext_->infoEnabled_; + } + void EnableTraceLevel(bool enabled) { boost::mutex::scoped_lock lock(loggingMutex_); @@ -464,6 +566,14 @@ } } + bool IsTraceLevelEnable() + { + boost::mutex::scoped_lock lock(loggingMutex_); + assert(loggingContext_.get() != NULL); + + return loggingContext_->traceEnabled_; + } + static void CheckFile(std::auto_ptr<std::ofstream>& f) { @@ -664,35 +774,6 @@ } } - - - - /* - struct FunctionCallingStream : std::ostream, std::streambuf - { - template<typename T> - FunctionCallingStream(T func) : std::ostream(this), func_(func) {} - - int overflow(int c) - { - if (c != '\n') - { - currentLine_ - } - else - { - func_(currentLine_.str().c_str()); - currentLine_.str(""); - currentLine_.clear(""); - } - return 0; - } - - private: - std::stringstream currentLine_; - }; - */ - void SetErrorWarnInfoLoggingStreams(std::ostream* errorStream, std::ostream* warningStream, std::ostream* infoStream)
--- a/Core/Logging.h Wed Apr 24 07:51:48 2019 +0200 +++ b/Core/Logging.h Tue May 07 11:23:11 2019 +0200 @@ -29,8 +29,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. **/ - - #pragma once #include <iostream> @@ -81,18 +79,24 @@ void EnableTraceLevel(bool enabled); -#ifdef __EMSCRIPTEN__ - // calling this function will change the error_, warning_ and info_ - // stream objects so that their operator<< writes into the browser - // console using emscripten_console_error(), emscripten_console_warn() - // and emscripten_console_log() - void EnableEmscriptenLogging(); -#endif + bool IsTraceLevelEnabled(); + + bool IsInfoLevelEnabled(); void SetTargetFile(const std::string& path); void SetTargetFolder(const std::string& path); +#if ORTHANC_ENABLE_LOGGING_STDIO == 1 + typedef void (*LoggingFunction)(const char*); + void SetErrorWarnInfoTraceLoggingFunctions( + LoggingFunction errorLogFunc, + LoggingFunction warningLogfunc, + LoggingFunction infoLogFunc, + LoggingFunction traceLogFunc); +#endif + + struct NullStream : public std::ostream { NullStream() : @@ -110,13 +114,11 @@ } } - #if ORTHANC_ENABLE_LOGGING != 1 # define LOG(level) ::Orthanc::Logging::NullStream() # define VLOG(level) ::Orthanc::Logging::NullStream() - #elif (ORTHANC_ENABLE_LOGGING_PLUGIN == 1 || \ ORTHANC_ENABLE_LOGGING_STDIO == 1) @@ -233,27 +235,6 @@ void DiscardLoggingMemento(LoggingMemento memento); /** - std::streambuf subclass used in FunctionCallingStream - */ - template<typename T> - class FuncStreamBuf : public std::stringbuf - { - public: - FuncStreamBuf(T func) : func_(func) {} - - virtual int sync() - { - std::string text = this->str(); - const char* buf = text.c_str(); - func_(buf); - this->str(""); - return 0; - } - private: - T func_; - }; - - /** Set custom logging streams for the error, warning and info logs. This function may not be called if a log file or folder has been set beforehand. All three pointers must be valid and cannot be NULL. @@ -268,6 +249,19 @@ void SetErrorWarnInfoLoggingStreams(std::ostream* errorStream, std::ostream* warningStream, std::ostream* infoStream); + +#ifdef __EMSCRIPTEN__ + /** + This function will change the logging streams so that the logging functions + provided by emscripten html5.h API functions are used : it will change the + error_, warning_ and info_ stream objects so that their operator<< writes + into the browser console using emscripten_console_error(), + emscripten_console_warn() and emscripten_console_log(). This will allow for + logging levels to be correctly handled by the browser when the code executes + in Web Assembly + */ + void EnableEmscriptenLogging(); +#endif } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/LoggingUtils.h Tue May 07 11:23:11 2019 +0200 @@ -0,0 +1,30 @@ +#include <sstream> +#include <iostream> + +namespace Orthanc +{ + namespace Logging + { + + /** + std::streambuf subclass used in FunctionCallingStream + */ + template<typename T> + class FuncStreamBuf : public std::stringbuf + { + public: + FuncStreamBuf(T func) : func_(func) {} + + virtual int sync() + { + std::string text = this->str(); + const char* buf = text.c_str(); + func_(buf); + this->str(""); + return 0; + } + private: + T func_; + }; + } +} \ No newline at end of file
--- a/LinuxCompilation.txt Wed Apr 24 07:51:48 2019 +0200 +++ b/LinuxCompilation.txt Tue May 07 11:23:11 2019 +0200 @@ -99,21 +99,19 @@ ------------------------------ # sudo apt-get install build-essential unzip cmake mercurial \ - uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \ - libgtest-dev libpng-dev libsqlite3-dev libssl-dev libjpeg-dev \ - zlib1g-dev libdcmtk2-dev libboost1.48-all-dev libwrap0-dev \ + uuid-dev libcurl4-openssl-dev liblua5.1-0-dev \ + libgtest-dev libpng-dev libsqlite3-dev libssl-dev libjpeg-dev \ + zlib1g-dev libdcmtk2-dev libboost1.48-all-dev libwrap0-dev \ libcharls-dev # cmake "-DDCMTK_LIBRARIES=boost_locale;CharLS;dcmjpls;wrap;oflog" \ -DALLOW_DOWNLOADS=ON \ - -DUSE_SYSTEM_CIVETWEB=OFF \ - -DUSE_SYSTEM_JSONCPP=OFF \ - -DUSE_SYSTEM_PUGIXML=OFF \ + -DUSE_SYSTEM_CIVETWEB=OFF \ + -DUSE_SYSTEM_JSONCPP=OFF \ + -DUSE_SYSTEM_PUGIXML=OFF \ -DUSE_GOOGLE_TEST_DEBIAN_PACKAGE=ON \ -DCMAKE_BUILD_TYPE=Release \ - ~/Orthanc - - + ~/Orthanc SUPPORTED - Ubuntu 14.04 LTS and 16.04 LTS ------------------------------------------
--- a/UnitTestsSources/LoggingTests.cpp Wed Apr 24 07:51:48 2019 +0200 +++ b/UnitTestsSources/LoggingTests.cpp Tue May 07 11:23:11 2019 +0200 @@ -36,6 +36,7 @@ #include <sstream> #include "../Core/Logging.h" +#include "../Core/LoggingUtils.h" using namespace Orthanc::Logging; @@ -66,11 +67,19 @@ If the log line cannot be matched, the function returns false. */ + +#ifdef WIN32 +# define EOLSTRING "\r\n" +#else +# define EOLSTRING "\n" +#endif + static bool GetLogLinePayload(std::string& payload, const std::string& logLine) { const char* regexStr = "[A-Z][0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{6} " - "[a-zA-Z\\.\\-_]+:[0-9]+\\] (.*)\r\n$"; + "[a-zA-Z\\.\\-_]+:[0-9]+\\] (.*)" EOLSTRING "$"; + boost::regex regexObj(regexStr); //std::stringstream regexSStr; @@ -109,7 +118,7 @@ { LoggingMementoScope loggingConfiguration; - EnableTraceLevel(TRUE); + EnableTraceLevel(true); typedef void(*LoggingFunctionFunc)(const char*); @@ -132,6 +141,7 @@ testErrorStream.clear(); std::string payload; bool ok = GetLogLinePayload(payload, logLine); + ASSERT_TRUE(ok); ASSERT_STREQ(payload.c_str(), text); } @@ -144,6 +154,7 @@ testErrorStream.clear(); std::string payload; bool ok = GetLogLinePayload(payload, logLine); + ASSERT_TRUE(ok); ASSERT_STREQ(payload.c_str(), text); } @@ -155,6 +166,7 @@ testWarningStream.clear(); std::string payload; bool ok = GetLogLinePayload(payload, logLine); + ASSERT_TRUE(ok); ASSERT_STREQ(payload.c_str(), text); } @@ -166,6 +178,7 @@ testInfoStream.clear(); std::string payload; bool ok = GetLogLinePayload(payload, logLine); + ASSERT_TRUE(ok); ASSERT_STREQ(payload.c_str(), text); } }