Merge pull request #270 from oatpp/configurable_loglevels

Proposal for #261: Fine grained configurable Loglevel
This commit is contained in:
Leonid Stryzhevskyi 2020-07-08 14:44:23 +03:00 committed by GitHub
commit 7a047df390
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 223 additions and 22 deletions

View File

@ -7,6 +7,7 @@
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
* Benedikt-Alexander Mokroß <oatpp@bamkrs.de>
*
* 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<std::chrono::seconds>(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<std::chrono::microseconds>(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<DefaultLogger>());
@ -239,6 +259,10 @@ void Environment::setLogger(const std::shared_ptr<Logger>& logger){
m_logger = logger;
}
std::shared_ptr<Logger> 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<char[]>(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);
}

View File

@ -7,6 +7,7 @@
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
* Benedikt-Alexander Mokroß <oatpp@bamkrs.de>
*
* 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>& logger);
/**
* Gets the current environment logger
* @return - current logger
*/
static std::shared_ptr<Logger> getLogger();
/**
* Print debug information of compilation config.<br>
* Print values for: <br>

View File

@ -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
@ -96,8 +98,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)

View File

@ -57,6 +57,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"
@ -77,6 +78,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);

View File

@ -0,0 +1,60 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
* Benedikt-Alexander Mokroß <oatpp@bamkrs.de>
*
* 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::DefaultLogger>(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");
}
}}}

View File

@ -0,0 +1,43 @@
/***************************************************************************
*
* Project _____ __ ____ _ _
* ( _ ) /__\ (_ _)_| |_ _| |_
* )(_)( /(__)\ )( (_ _)(_ _)
* (_____)(__)(__)(__) |_| |_|
*
*
* Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
* Benedikt-Alexander Mokroß <oatpp@bamkrs.de>
*
* 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 */