diff --git a/examples/c++/logger.cxx b/examples/c++/logger.cxx new file mode 100644 index 00000000..2d86ccba --- /dev/null +++ b/examples/c++/logger.cxx @@ -0,0 +1,35 @@ +#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) << "Testing the upm logger"; + + // Launching 5 threads + for (int i = 0; i < 5; ++i) { + threads.push_back(std::thread(print)); + } + + for (auto& thread : threads) { + thread.join(); + } + + 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..71cbe1a1 --- /dev/null +++ b/include/upm_logger.hpp @@ -0,0 +1,131 @@ +/* + * 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 +#include +#include +#include +#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) << __FILE__ << " " \ + << __FUNCTION__ << " " \ + << __LINE__ << ": " + +#define LOG_FILE "/var/log/upm.log" + +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& 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; + std::ofstream logStream; + static std::mutex logMutex; + public: + static const std::string& getLogLevelName(UpmLogLevel level); + private: + void write(std::ostringstream& os); + }; + + 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() + { + static UpmLogLevel reportingLevel = LOG_DEBUG; + + return reportingLevel; + } + + std::ostringstream& UPM_LOGGER::log(UpmLogLevel level) + { + using namespace std::chrono; + + os << "UPM - " << duration_cast + (system_clock::now().time_since_epoch()).count(); + os << " " << getLogLevelName(level) << " "; + + logLevel = level; + + return os; + } + + UPM_LOGGER::~UPM_LOGGER() + { + os << std::endl; + + write(os); + } +}