From e280742a6c9b29b4c44f0e20250fee452d16329e Mon Sep 17 00:00:00 2001 From: Bechir Braham Date: Tue, 26 Mar 2024 17:40:19 +0100 Subject: [PATCH] add logger class (#29) * add logger class * add LOCATION macro for logger * added printing in files --- CMakeLists.txt | 3 +- examples/CMakeLists.txt | 15 ++- .../{json_file_read.cpp => json_example.cpp} | 6 + examples/logger_example.cpp | 36 +++++ ...{numpy_file_read.cpp => numpy_example.cpp} | 0 utils/CMakeLists.txt | 4 + utils/include/aare/utils/logger.hpp | 123 ++++++++++++++++++ utils/src/logger.cpp | 14 ++ utils/test/logger.test.cpp | 2 + 9 files changed, 195 insertions(+), 8 deletions(-) rename examples/{json_file_read.cpp => json_example.cpp} (91%) create mode 100644 examples/logger_example.cpp rename examples/{numpy_file_read.cpp => numpy_example.cpp} (100%) create mode 100644 utils/CMakeLists.txt create mode 100644 utils/include/aare/utils/logger.hpp create mode 100644 utils/src/logger.cpp create mode 100644 utils/test/logger.test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b227b2..239c51d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,11 +98,12 @@ endif() add_subdirectory(core) add_subdirectory(file_io) +add_subdirectory(utils) #Overall target to link to when using the library add_library(aare INTERFACE) -target_link_libraries(aare INTERFACE core file_io) +target_link_libraries(aare INTERFACE core file_io utils) target_include_directories(aare INTERFACE $ $ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 90e7c86..a5f7f23 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,12 +1,13 @@ -add_executable(json_example json_file_read.cpp) -add_executable(numpy_example numpy_file_read.cpp) + +set(EXAMPLE_LIST "json_example;logger_example;numpy_example") +foreach(example ${EXAMPLE_LIST}) + add_executable(${example} ${example}.cpp) + target_link_libraries(${example} PUBLIC aare PRIVATE aare_compiler_flags) + + +endforeach() -target_link_libraries(json_example PRIVATE aare_compiler_flags) -target_link_libraries(numpy_example PRIVATE aare_compiler_flags) - -target_link_libraries(json_example PUBLIC aare) -target_link_libraries(numpy_example PUBLIC aare) diff --git a/examples/json_file_read.cpp b/examples/json_example.cpp similarity index 91% rename from examples/json_file_read.cpp rename to examples/json_example.cpp index 026e8fa..ae668d4 100644 --- a/examples/json_file_read.cpp +++ b/examples/json_example.cpp @@ -1,6 +1,7 @@ // Your First C++ Program #include "aare/ContextManager.hpp" #include +#include "aare/utils/logger.hpp" #define AARE_ROOT_DIR_VAR "PROJECT_ROOT_DIR" @@ -26,4 +27,9 @@ int main() { test(file, 2); test(file, 9); + aare::logger::debug(LOCATION,"Hello", "World"); + + + + } \ No newline at end of file diff --git a/examples/logger_example.cpp b/examples/logger_example.cpp new file mode 100644 index 0000000..9d8734c --- /dev/null +++ b/examples/logger_example.cpp @@ -0,0 +1,36 @@ +#include "aare/utils/logger.hpp" +#include +#include + +int main() { + aare::logger::debug(LOCATION, "hello", 1, "world", std::vector{1, 2, 3, 4, 5}); + aare::logger::debug(LOCATION, "setting verbosity to INFO"); + aare::logger::set_verbosity(aare::logger::INFO); + aare::logger::debug(LOCATION, "NOTHING SHOULD BE PRINTED"); + aare::logger::info(LOCATION, "info printed"); + + + // writing to file + std::ofstream textfile; + textfile.open("Test.txt"); + aare::logger::set_streams(textfile.rdbuf()); + aare::logger::info(LOCATION, "info printed to file"); + + + + // writing with a local logger instance + aare::logger::Logger logger; + logger.set_verbosity(aare::logger::WARNING); + logger.debug(LOCATION, "NOTHING SHOULD BE PRINTED"); + logger.info(LOCATION, "NOTHING SHOULD BE PRINTED"); + logger.warn(LOCATION, "warning printed in std::cout"); + aare::logger::info(LOCATION, "info printed in file ##"); + textfile.close(); + + + // setting file output by path + // user doesn't have to close file + aare::logger::set_output_file("Test2.txt"); + aare::logger::info(LOCATION, "info printed to Test2.txt"); + return 0; +} \ No newline at end of file diff --git a/examples/numpy_file_read.cpp b/examples/numpy_example.cpp similarity index 100% rename from examples/numpy_file_read.cpp rename to examples/numpy_example.cpp diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt new file mode 100644 index 0000000..8a554b8 --- /dev/null +++ b/utils/CMakeLists.txt @@ -0,0 +1,4 @@ +add_library(utils STATIC src/logger.cpp) +target_include_directories(utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + + diff --git a/utils/include/aare/utils/logger.hpp b/utils/include/aare/utils/logger.hpp new file mode 100644 index 0000000..1ed5bbc --- /dev/null +++ b/utils/include/aare/utils/logger.hpp @@ -0,0 +1,123 @@ +#pragma once +#include +#include +#include +#include + +#define LOCATION std::string(__FILE__) + std::string(":") + std::to_string(__LINE__) + ":" + std::string(__func__) + ":" + +// operator overload to print vectors +// typename T must be printable (i.e. have the << operator) +template std::ostream &operator<<(std::ostream &out, const std::vector &v) { + out << "["; + size_t last = v.size() - 1; + for (size_t i = 0; i < v.size(); ++i) { + out << v[i]; + if (i != last) + out << ", "; + } + out << "]"; + return out; +} + +namespace aare { + +namespace logger { +enum LOGGING_LEVEL { + DEBUG = 0, + INFO = 1, + WARNING = 2, + ERROR = 3 + +}; + +class Logger { + + std::streambuf *standard_buf = std::cout.rdbuf(); + std::streambuf *error_buf = std::cerr.rdbuf(); + std::ostream *standard_output; + std::ostream *error_output; + LOGGING_LEVEL VERBOSITY_LEVEL = LOGGING_LEVEL::DEBUG; + + std::ofstream out_file; + + public: + void set_output_file(std::string filename) { + if (out_file.is_open()) + out_file.close(); + out_file.open(filename); + set_streams(out_file.rdbuf()); + } + void set_streams(std::streambuf *out, std::streambuf *err) { + delete standard_output; + delete error_output; + standard_output = new std::ostream(out); + error_output = new std::ostream(err); + } + void set_streams(std::streambuf *out) { set_streams(out, out); } + void set_verbosity(LOGGING_LEVEL level) { VERBOSITY_LEVEL = level; } + Logger() { + standard_output = new std::ostream(standard_buf); + error_output = new std::ostream(error_buf); + } + + ~Logger() { + if (out_file.is_open()) + out_file.close(); + + standard_output->flush(); + error_output->flush(); + delete standard_output; + delete error_output; + } + template void log(const Strings... s) { + if (level >= VERBOSITY_LEVEL) + log_(s...); + } + template void debug(const Strings... s) { log("[DEBUG]", s...); } + template void info(const Strings... s) { log("[INFO]", s...); } + template void warn(const Strings... s) { log("[WARN]", s...); } + template void error(const Strings... s) { log("[ERROR]", s...); } + + private: + template void log_() { + if (level == LOGGING_LEVEL::ERROR) { + *error_output << std::endl; + } else { + *standard_output << std::endl; + } + } + template void log_(First arg, const Strings... s) { + if (level == LOGGING_LEVEL::ERROR) { + *error_output << (arg) << ' '; + error_output->flush(); + } else { + *standard_output << (arg) << ' '; + standard_output->flush(); + } + log_(s...); + } +}; + +namespace internal { + +extern aare::logger::Logger logger_instance; +} // namespace internal + +template void log(const Strings... s) { + internal::logger_instance.log(s...); +} +template void debug(const Strings... s) { internal::logger_instance.debug(s...); } +template void info(const Strings... s) { internal::logger_instance.info(s...); } +template void warn(const Strings... s) { internal::logger_instance.warn(s...); } +template void error(const Strings... s) { internal::logger_instance.error(s...); } + +extern void set_streams(std::streambuf *out, std::streambuf *err); +extern void set_streams(std::streambuf *out); +extern void set_verbosity(LOGGING_LEVEL level); +extern void set_output_file(std::string filename); +extern Logger &get_logger_instance(); + +} // namespace logger + +} // namespace aare \ No newline at end of file diff --git a/utils/src/logger.cpp b/utils/src/logger.cpp new file mode 100644 index 0000000..e8adb77 --- /dev/null +++ b/utils/src/logger.cpp @@ -0,0 +1,14 @@ +#include "aare/utils/logger.hpp" + +namespace aare { +namespace logger { +namespace internal { +aare::logger::Logger logger_instance = aare::logger::Logger(); +} // namespace internal +void set_streams(std::streambuf *out, std::streambuf *err) { internal::logger_instance.set_streams(out, err); } +void set_streams(std::streambuf *out) { internal::logger_instance.set_streams(out); } +void set_verbosity(LOGGING_LEVEL level) { internal::logger_instance.set_verbosity(level); } +Logger &get_logger_instance() { return internal::logger_instance; } +void set_output_file(std::string filename){ internal::logger_instance.set_output_file(filename); } +} // namespace logger +} // namespace aare \ No newline at end of file diff --git a/utils/test/logger.test.cpp b/utils/test/logger.test.cpp new file mode 100644 index 0000000..a6703c8 --- /dev/null +++ b/utils/test/logger.test.cpp @@ -0,0 +1,2 @@ +#include "aare/utils/logger.hpp" +#include