diff --git a/src/oatpp/core/base/Environment.cpp b/src/oatpp/core/base/Environment.cpp index f5d9c236..cf22c140 100644 --- a/src/oatpp/core/base/Environment.cpp +++ b/src/oatpp/core/base/Environment.cpp @@ -7,6 +7,7 @@ * * * Copyright 2018-present, Leonid Stryzhevskyi + * Benedikt-Alexander Mokroß * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,7 +58,7 @@ DefaultLogger::DefaultLogger(const Config& config) : m_config(config) {} -void DefaultLogger::log(v_int32 priority, const std::string& tag, const std::string& message) { +void DefaultLogger::log(v_uint32 priority, const std::string& tag, const std::string& message) { bool indent = false; auto time = std::chrono::system_clock::now().time_since_epoch(); @@ -89,7 +90,7 @@ void DefaultLogger::log(v_int32 priority, const std::string& tag, const std::str std::cout << " " << priority << " |"; } - if(m_config.timeFormat) { + if (m_config.timeFormat) { time_t seconds = std::chrono::duration_cast(time).count(); struct tm now; localtime_r(&seconds, &now); @@ -103,7 +104,7 @@ void DefaultLogger::log(v_int32 priority, const std::string& tag, const std::str indent = true; } - if(m_config.printTicks) { + if (m_config.printTicks) { auto ticks = std::chrono::duration_cast(time).count(); if(indent) { std::cout << " "; @@ -112,13 +113,32 @@ void DefaultLogger::log(v_int32 priority, const std::string& tag, const std::str indent = true; } - if(indent) { + if (indent) { std::cout << "|"; } - std::cout << " " << tag << ":" << message << std::endl; + + if (message.empty()) { + std::cout << " " << tag << std::endl; + } else { + std::cout << " " << tag << ":" << message << std::endl; + } } +void DefaultLogger::enablePriority(v_uint32 priority) { + m_config.logMask |= (1 << priority); +} + +void DefaultLogger::disablePriority(v_uint32 priority) { + m_config.logMask &= ~(1 << priority); +} + +bool DefaultLogger::isLogPriorityEnabled(v_uint32 priority) { + if (priority > PRIORITY_E) { + return true; + } + return m_config.logMask & (1 << priority); +} void Environment::init() { init(std::make_shared()); @@ -239,6 +259,10 @@ void Environment::setLogger(const std::shared_ptr& logger){ m_logger = logger; } +std::shared_ptr Environment::getLogger() { + return m_logger; +} + void Environment::printCompilationConfig() { OATPP_LOGD("oatpp-version", OATPP_VERSION); @@ -270,14 +294,32 @@ void Environment::log(v_int32 priority, const std::string& tag, const std::strin } void Environment::logFormatted(v_int32 priority, const std::string& tag, const char* message, ...) { - if(message == nullptr) { - message = "[null]"; + // do we have a logger and the priority is enabled? + if (m_logger == nullptr || !m_logger->isLogPriorityEnabled(priority)) { + return; } - char buffer[4097]; + // if we dont need to format anything, just print the message + if(message == nullptr) { + log(priority, tag, std::string()); + return; + } + // check how big our buffer has to be va_list args; - va_start (args, message); - vsnprintf(buffer, 4096, message, args); - log(priority, tag, buffer); + va_start(args, message); + v_buff_size allocsize = vsnprintf(nullptr, 0, message, args) + 1; + va_end(args); + // alloc the buffer (or the max size) + if (allocsize > m_logger->getMaxFormattingBufferSize()) { + allocsize = m_logger->getMaxFormattingBufferSize(); + } + auto buffer = std::unique_ptr(new char[allocsize]); + memset(buffer.get(), 0, allocsize); + // actually format + va_start(args, message); + vsnprintf(buffer.get(), allocsize, message, args); + // call (user) providen log function + log(priority, tag, buffer.get()); + // cleanup va_end(args); } diff --git a/src/oatpp/core/base/Environment.hpp b/src/oatpp/core/base/Environment.hpp index 8b951fec..c720bc18 100644 --- a/src/oatpp/core/base/Environment.hpp +++ b/src/oatpp/core/base/Environment.hpp @@ -7,6 +7,7 @@ * * * Copyright 2018-present, Leonid Stryzhevskyi + * Benedikt-Alexander Mokroß * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -92,27 +93,27 @@ public: /** * Log priority V-verbouse. */ - static constexpr v_int32 PRIORITY_V = 0; + static constexpr v_uint32 PRIORITY_V = 0; /** * Log priority D-debug. */ - static constexpr v_int32 PRIORITY_D = 1; + static constexpr v_uint32 PRIORITY_D = 1; /** * Log priority I-Info. */ - static constexpr v_int32 PRIORITY_I = 2; + static constexpr v_uint32 PRIORITY_I = 2; /** * Log priority W-Warning. */ - static constexpr v_int32 PRIORITY_W = 3; + static constexpr v_uint32 PRIORITY_W = 3; /** * Log priority E-error. */ - static constexpr v_int32 PRIORITY_E = 4; + static constexpr v_uint32 PRIORITY_E = 4; public: /** * Virtual Destructor. @@ -125,7 +126,24 @@ public: * @param tag - tag of the log message. * @param message - message. */ - virtual void log(v_int32 priority, const std::string& tag, const std::string& message) = 0; + virtual void log(v_uint32 priority, const std::string& tag, const std::string& message) = 0; + + /** + * Returns wether or not a priority should be logged/printed + * @param priority + * @return - true if given priority should be logged + */ + virtual bool isLogPriorityEnabled(v_uint32 priority) { + return true; + } + + /** + * Should return the maximum amount of bytes that should be allocated for a single log message + * @return - maximum buffer size + */ + virtual v_buff_size getMaxFormattingBufferSize() { + return 4096; + } }; /** @@ -143,9 +161,10 @@ public: * @param tfmt - time format. * @param printMicroTicks - show ticks in microseconds. */ - Config(const char* tfmt, bool printMicroTicks) + Config(const char* tfmt, bool printMicroTicks, v_uint32 initialLogMask) : timeFormat(tfmt) , printTicks(printMicroTicks) + , logMask(initialLogMask) {} /** @@ -158,6 +177,11 @@ public: * Print micro-ticks in the log message. */ bool printTicks; + + /** + * Log mask to enable/disable certain priorities + */ + v_uint32 logMask; }; private: Config m_config; @@ -168,7 +192,11 @@ public: * Constructor. * @param config - Logger config. */ - DefaultLogger(const Config& config = Config("%Y-%m-%d %H:%M:%S", true)); + DefaultLogger(const Config& config = Config( + "%Y-%m-%d %H:%M:%S", + true, + (1 << PRIORITY_V) | (1 << PRIORITY_D) | (1 << PRIORITY_I) | (1 << PRIORITY_W) | (1 << PRIORITY_E) + )); /** * Log message with priority, tag, message. @@ -176,7 +204,26 @@ public: * @param tag - tag of the log message. * @param message - message. */ - void log(v_int32 priority, const std::string& tag, const std::string& message) override; + void log(v_uint32 priority, const std::string& tag, const std::string& message) override; + + /** + * Enables logging of a priorities for this instance + * @param priority - the priority level to enable + */ + void enablePriority(v_uint32 priority); + + /** + * Disables logging of a priority for this instance + * @param priority - the priority level to disable + */ + void disablePriority(v_uint32 priority); + + /** + * Returns wether or not a priority should be logged/printed + * @param priority + * @return - true if given priority should be logged + */ + bool isLogPriorityEnabled(v_uint32 priority) override; }; /** @@ -315,6 +362,12 @@ public: */ static void setLogger(const std::shared_ptr& logger); + /** + * Gets the current environment logger + * @return - current logger + */ + static std::shared_ptr getLogger(); + /** * Print debug information of compilation config.
* Print values for:
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ac34c615..fcf7f160 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,8 @@ add_executable(oatppAllTests oatpp/core/async/LockTest.hpp oatpp/core/base/CommandLineArgumentsTest.cpp oatpp/core/base/CommandLineArgumentsTest.hpp + oatpp/core/base/LoggerTest.cpp + oatpp/core/base/LoggerTest.hpp oatpp/core/base/collection/LinkedListTest.cpp oatpp/core/base/collection/LinkedListTest.hpp oatpp/core/base/memory/MemoryPoolTest.cpp @@ -98,8 +100,7 @@ add_executable(oatppAllTests oatpp/web/app/ControllerAsync.hpp oatpp/web/app/DTOs.hpp oatpp/web/app/ControllerWithInterceptors.hpp - oatpp/web/app/ControllerWithInterceptorsAsync.hpp -) + oatpp/web/app/ControllerWithInterceptorsAsync.hpp) target_link_libraries(oatppAllTests PRIVATE oatpp PRIVATE oatpp-test) diff --git a/test/oatpp/AllTestsMain.cpp b/test/oatpp/AllTestsMain.cpp index 6e32a577..fe53462b 100644 --- a/test/oatpp/AllTestsMain.cpp +++ b/test/oatpp/AllTestsMain.cpp @@ -58,6 +58,7 @@ #include "oatpp/core/base/memory/MemoryPoolTest.hpp" #include "oatpp/core/base/memory/PerfTest.hpp" #include "oatpp/core/base/CommandLineArgumentsTest.hpp" +#include "oatpp/core/base/LoggerTest.hpp" #include "oatpp/core/async/Coroutine.hpp" #include "oatpp/core/Types.hpp" @@ -78,6 +79,7 @@ void runTests() { OATPP_LOGD("aaa", "action size=%d", sizeof(oatpp::async::Action)); OATPP_RUN_TEST(oatpp::test::base::CommandLineArgumentsTest); + OATPP_RUN_TEST(oatpp::test::base::LoggerTest); OATPP_RUN_TEST(oatpp::test::memory::MemoryPoolTest); OATPP_RUN_TEST(oatpp::test::memory::PerfTest); diff --git a/test/oatpp/core/base/LoggerTest.cpp b/test/oatpp/core/base/LoggerTest.cpp new file mode 100644 index 00000000..cca4ba55 --- /dev/null +++ b/test/oatpp/core/base/LoggerTest.cpp @@ -0,0 +1,60 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi + * Benedikt-Alexander Mokroß + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#include "LoggerTest.hpp" + +namespace oatpp { namespace test { namespace base { + +void LoggerTest::onRun() { + + auto logger = std::static_pointer_cast(oatpp::base::Environment::getLogger()); + + OATPP_LOGV("LoggerTest", "Verbose Log"); + OATPP_LOGD("LoggerTest", "Debug Log"); + OATPP_LOGI("LoggerTest", "Info Log"); + OATPP_LOGW("LoggerTest", "Warning Log"); + OATPP_LOGE("LoggerTest", "Error Log"); + + OATPP_LOGV("LoggerTest", "Disabling Debug Log"); + logger->disablePriority(oatpp::base::DefaultLogger::PRIORITY_D); + + OATPP_LOGV("LoggerTest", "Verbose Log"); + OATPP_LOGD("LoggerTest", "Debug Log"); + OATPP_LOGI("LoggerTest", "Info Log"); + OATPP_LOGW("LoggerTest", "Warning Log"); + OATPP_LOGE("LoggerTest", "Error Log"); + + OATPP_LOGV("LoggerTest", "Enabling Debug Log again"); + logger->enablePriority(oatpp::base::DefaultLogger::PRIORITY_D); + + OATPP_LOGV("LoggerTest", "Verbose Log"); + OATPP_LOGD("LoggerTest", "Debug Log"); + OATPP_LOGI("LoggerTest", "Info Log"); + OATPP_LOGW("LoggerTest", "Warning Log"); + OATPP_LOGE("LoggerTest", "Error Log"); + +} + +}}} diff --git a/test/oatpp/core/base/LoggerTest.hpp b/test/oatpp/core/base/LoggerTest.hpp new file mode 100644 index 00000000..06c63f5d --- /dev/null +++ b/test/oatpp/core/base/LoggerTest.hpp @@ -0,0 +1,43 @@ +/*************************************************************************** + * + * Project _____ __ ____ _ _ + * ( _ ) /__\ (_ _)_| |_ _| |_ + * )(_)( /(__)\ )( (_ _)(_ _) + * (_____)(__)(__)(__) |_| |_| + * + * + * Copyright 2018-present, Leonid Stryzhevskyi + * Benedikt-Alexander Mokroß + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************/ + +#ifndef oatpp_test_base_LoggerTest_hpp +#define oatpp_test_base_LoggerTest_hpp + +#include "oatpp-test/UnitTest.hpp" + +namespace oatpp { namespace test { namespace base { + +class LoggerTest : public UnitTest{ + public: + + LoggerTest():UnitTest("TEST[base::LoggerTest]"){} + void onRun() override; + +}; + +}}} + +#endif /* oatpp_test_base_LoggerTest_hpp */