diff --git a/sample/CMakeLists.txt b/sample/CMakeLists.txt index a1d2e21c1..dca5fd59b 100644 --- a/sample/CMakeLists.txt +++ b/sample/CMakeLists.txt @@ -1,36 +1,35 @@ -add_executable(a api.cpp) -target_link_libraries(a - slsDetectorShared +add_executable(using_logger using_logger.cpp) +target_link_libraries(using_logger slsSupportLib pthread rt ) -set_target_properties(a PROPERTIES +set_target_properties(using_logger PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) -add_executable(result useResult.cpp) -target_link_libraries(result - slsDetectorShared -) +# add_executable(result useResult.cpp) +# target_link_libraries(result +# slsDetectorShared +# ) -set_target_properties(result PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin -) +# set_target_properties(result PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +# ) -add_executable(udp udp.cpp) -target_link_libraries(udp - slsDetectorShared - slsSupportLib - pthread - rt - fmt -) +# add_executable(udp udp.cpp) +# target_link_libraries(udp +# slsDetectorShared +# slsSupportLib +# pthread +# rt +# fmt +# ) -set_target_properties(udp PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin -) +# set_target_properties(udp PROPERTIES +# RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin +# ) diff --git a/sample/using_logger.cpp b/sample/using_logger.cpp new file mode 100644 index 000000000..394dbca0c --- /dev/null +++ b/sample/using_logger.cpp @@ -0,0 +1,32 @@ +#include "logger.h" +#include "logger2.h" + +#include +#include +int main(){ + + std::cout << "Compare output between old and new:\n"; + FILE_LOG(logINFO) << "Old message"; + LOG(logINFO) << "New message"; + FILE_LOG(logERROR) << "Old error"; + LOG(logERROR) << "New error"; + FILE_LOG(logWARNING) << "Old warning"; + LOG(logWARNING) << "New warning"; + + // // sls::Logger::ReportingLevel() = logERROR; + + // const auto N = 100000; + // auto t0 = std::chrono::steady_clock::now(); + // for (int i = 0; i!=N; ++i){ + // // LOG(logWARNING) << "HEY"; + // FILE_LOG(logWARNING) << "HEY"; + // } + // auto t1 = std::chrono::steady_clock::now(); + // for (int i = 0; i!=N; ++i){ + // LOG(logWARNING) << "HEY"; + // } + // auto t2 = std::chrono::steady_clock::now(); + + // std::cout << "Old: " << (t1-t0).count() << "\n"; + // std::cout << "New: " << (t2-t1).count() << "\n"; +} \ No newline at end of file diff --git a/slsSupportLib/include/logger2.h b/slsSupportLib/include/logger2.h index 239a7567e..4be5da88f 100644 --- a/slsSupportLib/include/logger2.h +++ b/slsSupportLib/include/logger2.h @@ -1,33 +1,26 @@ #pragma once /*Utility to log to console*/ -#include "ansi.h" //Colors -#include "logger.h" +#include "ansi.h" //Colors +#include "logger.h" //for enum, to be removed #include -#include #include -#include -#include -/* -Define the max level that is visible -The compiler should optimize away any calls below -this level -*/ -#ifndef LOG_MAX_LEVEL -#define LOG_MAX_LEVEL logINFO +// Compiler should optimize away anything below this value +#ifndef LOG_MAX_REPORTING_LEVEL +#define LOG_MAX_REPORTING_LEVEL logINFO #endif namespace sls { class Logger { std::ostringstream os; - TLogLevel level = LOG_MAX_LEVEL; + TLogLevel level = LOG_MAX_REPORTING_LEVEL; public: Logger() = default; Logger(TLogLevel level) : level(level){}; ~Logger() { - // output happens in the destructor to allow for << + // output in the destructor to allow for << syntax os << Reset() << '\n'; std::clog << os.str(); // Single write } @@ -38,13 +31,14 @@ class Logger { } // Danger this buffer need as many elements as TLogLevel - static const char *Color(TLogLevel level) { + static const char *Color(TLogLevel level) noexcept { static const char *const colors[] = { RED BOLD, YELLOW BOLD, RESET, BLUE, RED, RESET, RESET, RESET, RESET, RESET, RESET, RESET}; return colors[level]; } - static const char *Reset() { + + static const char *Reset() noexcept { static const char *reset = RESET; return reset; } @@ -58,26 +52,32 @@ class Logger { } std::ostringstream &Get() { - os << Color(level); - os << "- " << Time(); - os << " " << ToString(level) << ": "; + os << Color(level) << "- " << Timestamp() << " " << ToString(level) + << ": "; return os; } - std::string Time(decltype(std::chrono::system_clock::now()) now = - std::chrono::system_clock::now()) { - std::ostringstream oss; - auto ms = std::chrono::duration_cast( - now.time_since_epoch()) % - 1000; - std::time_t now_time = std::chrono::system_clock::to_time_t(now); - oss << std::put_time(std::localtime(&now_time), "%H:%M:%S") << "." - << std::setw(3) << std::setfill('0') << ms.count(); - return oss.str(); + + std::string Timestamp() { + constexpr size_t buffer_len = 12; + char buffer[buffer_len]; + time_t t; + time(&t); + tm r; + strftime(buffer, buffer_len, "%X", localtime_r(&t, &r)); + buffer[buffer_len - 1] = '\0'; + struct timeval tv; + gettimeofday(&tv, nullptr); + constexpr size_t result_len = 100; + char result[result_len]; + snprintf(result, result_len, "%s.%03ld", buffer, + (long)tv.tv_usec / 1000); + result[result_len - 1] = '\0'; + return result; } }; #define LOG(level) \ - if (level > LOG_MAX_LEVEL) \ + if (level > LOG_MAX_REPORTING_LEVEL) \ ; \ else if (level > sls::Logger::ReportingLevel()) \ ; \ diff --git a/slsSupportLib/tests/test-logger.cpp b/slsSupportLib/tests/test-logger.cpp index a150ae812..bcf371683 100644 --- a/slsSupportLib/tests/test-logger.cpp +++ b/slsSupportLib/tests/test-logger.cpp @@ -6,54 +6,53 @@ #include #include -TEST_CASE("Get time"){ - auto now = std::chrono::system_clock::now(); - sls::Logger log; - auto time = log.Time(now); +using sls::Logger; +TEST_CASE("LogLevel to string") { + CHECK(Logger::ToString(logERROR) == "ERROR"); + CHECK(Logger::ToString(logWARNING) == "WARNING"); + CHECK(Logger::ToString(logINFOBLUE) == "INFO"); + CHECK(Logger::ToString(logINFOGREEN) == "INFO"); + CHECK(Logger::ToString(logINFORED) == "INFO"); + CHECK(Logger::ToString(logINFO) == "INFO"); + CHECK(Logger::ToString(logDEBUG) == "DEBUG"); + CHECK(Logger::ToString(logDEBUG1) == "DEBUG1"); + CHECK(Logger::ToString(logDEBUG2) == "DEBUG2"); + CHECK(Logger::ToString(logDEBUG3) == "DEBUG3"); + CHECK(Logger::ToString(logDEBUG4) == "DEBUG4"); + CHECK(Logger::ToString(logDEBUG5) == "DEBUG5"); } -TEST_CASE("fail"){ +TEST_CASE("get reset string"){ + std::string reset(Logger::Reset()); + CHECK(reset == RESET); +} - FILE_LOG(logINFO) << "A message"; - FILE_LOG(logWARNING) << "An error"; - FILE_LOG(logERROR) << "A warning"; +TEST_CASE("Test output") { -// sls::Logger::ReportingLevel() = logERROR; - // std::cout << sls::Logger::ReportingLevel() << '\n'; - LOG(logINFO) << "A new message"; - LOG(logERROR) << "A new error"; - LOG(logWARNING) << "A new warning"; + auto old_value = Logger::ReportingLevel(); - LOG(logDEBUG3) << "This should not be printed"; + Logger::ReportingLevel() = logERROR; + //Redirect std::clog to local buffer std::ostringstream local; auto clog_buff = std::clog.rdbuf(); std::clog.rdbuf(local.rdbuf()); - LOG(logERROR) << "This should also not be printed"; + //Try printing something with too low level + LOG(logDEBUG) << "This should not be printed"; + CHECK(local.str().empty()); + + //Try printing something with a higher level + LOG(logERROR) << "This should be printed"; + CHECK(!local.str().empty()); std::clog.rdbuf(clog_buff); // restore - LOG(logERROR) << "But this should"; - - std::cout << "we got: " << local.str() << '\n'; - - - // sls::Logger::ReportingLevel() = logDEBUG1; - // std::cout << sls::Logger::ReportingLevel() << '\n'; - // std::ostream& os = std::cout; - // Output2FILE::Stream(); - - // os << "hej pa dig\n"; - - // std::ostringstream oss; - // std::ostream& os = oss; - // auto& out = Output2FILE::Stream(); - // out = os; - // Output2FILE::Stream() = std::cout; - // FILE_LOG(logERROR) << "An error message"; - - - // CHECK(false); + Logger::ReportingLevel() = old_value; //reset + //Check that the message is in the printed string + auto r = local.str(); + auto pos = r.find("This should be printed"); + CHECK(pos != std::string::npos); + } \ No newline at end of file