From e3f1533652119df0fff20a4fee712aebb5b31538 Mon Sep 17 00:00:00 2001 From: UPSquared Date: Mon, 21 May 2018 19:13:18 +0300 Subject: [PATCH 1/5] logger initial commit --- examples/c++/logger.cxx | 17 +++++++++ include/upm_logger.hpp | 84 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 examples/c++/logger.cxx create mode 100644 include/upm_logger.hpp diff --git a/examples/c++/logger.cxx b/examples/c++/logger.cxx new file mode 100644 index 00000000..61cdd02c --- /dev/null +++ b/examples/c++/logger.cxx @@ -0,0 +1,17 @@ +#include "upm_logger.hpp" + +using namespace upm; + +int main() +{ + + UPM_LOGGER::getLogLevel() = LOG_ERROR; + + UPM_LOGGER().get(LOG_WARNING) << "a loop with 4 iterations"; + + for (int i = 0; i < 4; ++i) { + UPM_LOGGER().get(LOG_DEBUG) << "i = " << i; + } + + return 0; +} \ No newline at end of file diff --git a/include/upm_logger.hpp b/include/upm_logger.hpp new file mode 100644 index 00000000..f0a44519 --- /dev/null +++ b/include/upm_logger.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include +#include + +namespace upm { + + enum UpmLogLevel { + LOG_ERROR, + LOG_WARNING, + LOG_INFO, + LOG_DEBUG, + NA + }; + + static const std::string logLevelNames[] = { + "ERROR", + "WARNING", + "INFO", + "DEBUG", + "" + }; + + class UPM_LOGGER { + public: + UPM_LOGGER(); + virtual ~UPM_LOGGER(); + std::ostringstream& get(UpmLogLevel level = LOG_INFO); + static UpmLogLevel& getLogLevel(); + protected: + std::ostringstream os; + private: + UPM_LOGGER(const UPM_LOGGER&); + UPM_LOGGER& operator=(const UPM_LOGGER&); + private: + UpmLogLevel logLevel; + + public: + static const std::string& getLogLevelName(UpmLogLevel level) + { + if (level < LOG_ERROR || level >= NA) { + return NULL; + } + + return logLevelNames[level]; + } + }; + + UPM_LOGGER::UPM_LOGGER() {} + + + UpmLogLevel& UPM_LOGGER::getLogLevel() + { + static UpmLogLevel reportingLevel = LOG_DEBUG; + return reportingLevel; + } + + std::ostringstream& UPM_LOGGER::get(UpmLogLevel level) + { + using namespace std::chrono; + + os << "- " << duration_cast + (system_clock::now().time_since_epoch()).count(); + os << " " << getLogLevelName(level) << ": "; + os << std::string(level > LOG_DEBUG ? level - LOG_DEBUG : 0, '\t'); + logLevel = level; + + return os; + } + + UPM_LOGGER::~UPM_LOGGER() + { + if (logLevel >= UPM_LOGGER::getLogLevel()) { + os << std::endl; + fprintf(stderr, "%s", os.str().c_str()); + fflush(stderr); + } + } + +} + + From 9d6944f9b8a9246759b9b1afb1d18d4e27c39e1d Mon Sep 17 00:00:00 2001 From: UPSquared Date: Tue, 22 May 2018 17:33:49 +0300 Subject: [PATCH 2/5] added useful macro for logger --- examples/c++/logger.cxx | 6 +++--- include/upm_logger.hpp | 31 ++++++++++++++++++------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/examples/c++/logger.cxx b/examples/c++/logger.cxx index 61cdd02c..b4b1c0b4 100644 --- a/examples/c++/logger.cxx +++ b/examples/c++/logger.cxx @@ -5,12 +5,12 @@ using namespace upm; int main() { - UPM_LOGGER::getLogLevel() = LOG_ERROR; + UPM_LOGGER::LogLevel() = LOG_INFO; - UPM_LOGGER().get(LOG_WARNING) << "a loop with 4 iterations"; + UPM_LOG(LOG_WARNING) << "a loop with 4 iterations"; for (int i = 0; i < 4; ++i) { - UPM_LOGGER().get(LOG_DEBUG) << "i = " << i; + UPM_LOG(LOG_DEBUG) << "i = " << i; } return 0; diff --git a/include/upm_logger.hpp b/include/upm_logger.hpp index f0a44519..e5eb8a7d 100644 --- a/include/upm_logger.hpp +++ b/include/upm_logger.hpp @@ -5,6 +5,13 @@ #include #include +/* Helper macro for logger utility class. */ +#define UPM_LOG(log_level) \ + if ( log_level < UPM_LOGGER::LogLevel() ) \ + ; \ + else \ + UPM_LOGGER().log(log_level) + namespace upm { enum UpmLogLevel { @@ -27,14 +34,15 @@ namespace upm { public: UPM_LOGGER(); virtual ~UPM_LOGGER(); - std::ostringstream& get(UpmLogLevel level = LOG_INFO); - static UpmLogLevel& getLogLevel(); + std::ostringstream& log(UpmLogLevel level = LOG_ERROR); + static UpmLogLevel& LogLevel(); protected: std::ostringstream os; private: UPM_LOGGER(const UPM_LOGGER&); UPM_LOGGER& operator=(const UPM_LOGGER&); private: + // Track logLevel for this particular instance of UPM_LOGGER UpmLogLevel logLevel; public: @@ -51,20 +59,22 @@ namespace upm { UPM_LOGGER::UPM_LOGGER() {} - UpmLogLevel& UPM_LOGGER::getLogLevel() + UpmLogLevel& UPM_LOGGER::LogLevel() { static UpmLogLevel reportingLevel = LOG_DEBUG; + return reportingLevel; } - std::ostringstream& UPM_LOGGER::get(UpmLogLevel level) + std::ostringstream& UPM_LOGGER::log(UpmLogLevel level) { using namespace std::chrono; - os << "- " << duration_cast + os << "UPM - " << duration_cast (system_clock::now().time_since_epoch()).count(); os << " " << getLogLevelName(level) << ": "; os << std::string(level > LOG_DEBUG ? level - LOG_DEBUG : 0, '\t'); + logLevel = level; return os; @@ -72,13 +82,8 @@ namespace upm { UPM_LOGGER::~UPM_LOGGER() { - if (logLevel >= UPM_LOGGER::getLogLevel()) { - os << std::endl; - fprintf(stderr, "%s", os.str().c_str()); - fflush(stderr); - } + os << std::endl; + fprintf(stderr, "%s", os.str().c_str()); + fflush(stderr); } - } - - From 4ed5da009858d607cae69cb22acda11ff3a66965 Mon Sep 17 00:00:00 2001 From: UPSquared Date: Tue, 22 May 2018 18:11:27 +0300 Subject: [PATCH 3/5] time is now even more precise. added file, function, line macros --- include/upm_logger.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/upm_logger.hpp b/include/upm_logger.hpp index e5eb8a7d..629e4ed5 100644 --- a/include/upm_logger.hpp +++ b/include/upm_logger.hpp @@ -10,7 +10,9 @@ if ( log_level < UPM_LOGGER::LogLevel() ) \ ; \ else \ - UPM_LOGGER().log(log_level) + UPM_LOGGER().log(log_level) << __FILE__ << " " \ + << __FUNCTION__ << " " \ + << __LINE__ << ": " namespace upm { @@ -70,10 +72,9 @@ namespace upm { { using namespace std::chrono; - os << "UPM - " << duration_cast + os << "UPM - " << duration_cast (system_clock::now().time_since_epoch()).count(); - os << " " << getLogLevelName(level) << ": "; - os << std::string(level > LOG_DEBUG ? level - LOG_DEBUG : 0, '\t'); + os << " " << getLogLevelName(level) << " "; logLevel = level; From 046ac700715127cd12546d1e8f1a3cd5db269572 Mon Sep 17 00:00:00 2001 From: mihais Date: Tue, 5 Jun 2018 11:59:04 +0300 Subject: [PATCH 4/5] multithreaded initial support --- include/upm_logger.hpp | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/include/upm_logger.hpp b/include/upm_logger.hpp index 629e4ed5..941a2ec1 100644 --- a/include/upm_logger.hpp +++ b/include/upm_logger.hpp @@ -1,9 +1,11 @@ #pragma once #include +#include #include #include -#include +#include +#include /* Helper macro for logger utility class. */ #define UPM_LOG(log_level) \ @@ -14,6 +16,8 @@ << __FUNCTION__ << " " \ << __LINE__ << ": " +#define LOG_FILE "/var/log/upm.log" + namespace upm { enum UpmLogLevel { @@ -38,6 +42,9 @@ namespace upm { virtual ~UPM_LOGGER(); std::ostringstream& log(UpmLogLevel level = LOG_ERROR); static UpmLogLevel& LogLevel(); + + static std::ofstream logStream; + static std::mutex logMutex; protected: std::ostringstream os; private: @@ -56,6 +63,18 @@ namespace upm { return logLevelNames[level]; } + + public: + static void write(std::ostringstream& os) + { + + + std::lock_guard lock(logMutex); + + logStream.open(LOG_FILE, std::ios_base::app); + logStream << os.str(); + logStream.flush(); + } }; UPM_LOGGER::UPM_LOGGER() {} @@ -84,7 +103,7 @@ namespace upm { UPM_LOGGER::~UPM_LOGGER() { os << std::endl; - fprintf(stderr, "%s", os.str().c_str()); - fflush(stderr); + + write(os); } } From 43ecacfce73a049c5a667a100658522f6778bcbd Mon Sep 17 00:00:00 2001 From: UPSquared Date: Tue, 5 Jun 2018 15:33:02 +0300 Subject: [PATCH 5/5] example for logger class + minor improvements --- examples/c++/logger.cxx | 24 +++++++++++-- include/upm_logger.hpp | 74 ++++++++++++++++++++++++++--------------- 2 files changed, 69 insertions(+), 29 deletions(-) diff --git a/examples/c++/logger.cxx b/examples/c++/logger.cxx index b4b1c0b4..2d86ccba 100644 --- a/examples/c++/logger.cxx +++ b/examples/c++/logger.cxx @@ -1,16 +1,34 @@ +#include +#include + #include "upm_logger.hpp" using namespace upm; +void print() +{ + UPM_LOG(LOG_DEBUG) << "Thread " << std::this_thread::get_id() << ": running loop with 3 iterations"; + + for (int i = 0; i < 4; ++i) { + UPM_LOG(LOG_DEBUG) << std::this_thread::get_id() << ": i = " << i; + } +} + int main() { + std::vector threads; UPM_LOGGER::LogLevel() = LOG_INFO; - UPM_LOG(LOG_WARNING) << "a loop with 4 iterations"; + UPM_LOG(LOG_WARNING) << "Testing the upm logger"; - for (int i = 0; i < 4; ++i) { - UPM_LOG(LOG_DEBUG) << "i = " << i; + // Launching 5 threads + for (int i = 0; i < 5; ++i) { + threads.push_back(std::thread(print)); + } + + for (auto& thread : threads) { + thread.join(); } return 0; diff --git a/include/upm_logger.hpp b/include/upm_logger.hpp index 941a2ec1..71cbe1a1 100644 --- a/include/upm_logger.hpp +++ b/include/upm_logger.hpp @@ -1,3 +1,27 @@ +/* + * Author: Mihai Stefanescu + * Copyright (c) 2018 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + #pragma once #include @@ -38,13 +62,10 @@ namespace upm { class UPM_LOGGER { public: - UPM_LOGGER(); + UPM_LOGGER() {} virtual ~UPM_LOGGER(); std::ostringstream& log(UpmLogLevel level = LOG_ERROR); static UpmLogLevel& LogLevel(); - - static std::ofstream logStream; - static std::mutex logMutex; protected: std::ostringstream os; private: @@ -53,32 +74,33 @@ namespace upm { private: // Track logLevel for this particular instance of UPM_LOGGER UpmLogLevel logLevel; - + std::ofstream logStream; + static std::mutex logMutex; public: - static const std::string& getLogLevelName(UpmLogLevel level) - { - if (level < LOG_ERROR || level >= NA) { - return NULL; - } - - return logLevelNames[level]; - } - - public: - static void write(std::ostringstream& os) - { - - - std::lock_guard lock(logMutex); - - logStream.open(LOG_FILE, std::ios_base::app); - logStream << os.str(); - logStream.flush(); - } + static const std::string& getLogLevelName(UpmLogLevel level); + private: + void write(std::ostringstream& os); }; - UPM_LOGGER::UPM_LOGGER() {} + std::mutex UPM_LOGGER::logMutex; + void UPM_LOGGER::write(std::ostringstream& os) + { + std::lock_guard lock(logMutex); + + logStream.open(LOG_FILE, std::ios_base::app); + logStream << os.str(); + logStream.flush(); + } + + const std::string& UPM_LOGGER::getLogLevelName(UpmLogLevel level) + { + if (level < LOG_ERROR || level >= NA) { + return NULL; + } + + return logLevelNames[level]; + } UpmLogLevel& UPM_LOGGER::LogLevel() {