Merge pull request #83 from slsdetectorgroup/logger

New logger
This commit is contained in:
Dhanya Thattil
2020-03-09 17:46:18 +01:00
committed by GitHub
6 changed files with 206 additions and 23 deletions

View File

@@ -0,0 +1,82 @@
#pragma once
/*Utility to log to console*/
#include "ansi.h" //Colors
#include "logger.h" //for enum, to be removed
#include <iostream>
#include <sstream>
// 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_REPORTING_LEVEL;
public:
Logger() = default;
explicit Logger(TLogLevel level) : level(level){};
~Logger() {
// output in the destructor to allow for << syntax
os << RESET << '\n';
std::clog << os.str() << std::flush; // Single write
}
static TLogLevel &ReportingLevel() { // singelton eeh
static TLogLevel reportingLevel = logINFO;
return reportingLevel;
}
// Danger this buffer need as many elements as TLogLevel
static const char *Color(TLogLevel level) noexcept {
static const char *const colors[] = {
RED BOLD, YELLOW BOLD, BLUE, GREEN, RED, RESET,
RESET, RESET, RESET, RESET, RESET, RESET};
return colors[level];
}
// Danger this buffer need as many elements as TLogLevel
static std::string ToString(TLogLevel level) {
static const char *const buffer[] = {
"ERROR", "WARNING", "INFO", "INFO", "INFO", "INFO",
"DEBUG", "DEBUG1", "DEBUG2", "DEBUG3", "DEBUG4", "DEBUG5"};
return buffer[level];
}
std::ostringstream &Get() {
os << Color(level) << "- " << Timestamp() << " " << ToString(level)
<< ": ";
return os;
}
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_REPORTING_LEVEL) \
; \
else if (level > sls::Logger::ReportingLevel()) \
; \
else \
sls::Logger(level).Get()
} // namespace sls

View File

@@ -9,4 +9,5 @@ target_sources(tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/test-ToString.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-TypeTraits.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-UdpRxSocket.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-logger.cpp
)

View File

@@ -0,0 +1,53 @@
#include "catch.hpp"
#include "logger.h"
#include "logger2.h"
#include <iostream>
#include <fstream>
#include <chrono>
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("Test output") {
auto old_value = Logger::ReportingLevel();
Logger::ReportingLevel() = logERROR;
//Redirect std::clog to local buffer
std::ostringstream local;
auto clog_buff = std::clog.rdbuf();
std::clog.rdbuf(local.rdbuf());
//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
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);
}