Skip to content

Instantly share code, notes, and snippets.

@ZanzyTHEbar
Created March 12, 2024 16:16
Show Gist options
  • Save ZanzyTHEbar/ef56acd3dbc3a7754d2000646cdd47d6 to your computer and use it in GitHub Desktop.
Save ZanzyTHEbar/ef56acd3dbc3a7754d2000646cdd47d6 to your computer and use it in GitHub Desktop.
Logger using variadic templating
#pragma once
#include <algorithm>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <utilities/helpers.hpp>
class Logger {
public:
enum LogLevel_e : uint8_t { DEBUG, INFO, WARN, ERROR, FATAL, NUM_LOG_LEVELS };
protected:
std::string checkLogLevel(LogLevel_e log_level) {
static const std::array<std::string, NUM_LOG_LEVELS> logLevelStrings = {
"DEBUG", "INFO", "WARN", "ERROR", "FATAL"};
if (log_level >= 0 && log_level < NUM_LOG_LEVELS)
return logLevelStrings[log_level];
return "UNKNOWN";
}
template <typename... Args>
std::string handleInput(Args... args) {
std::stringstream ss;
// Fold expression to concatenate arguments
(ss << ... << args);
std::string message = ss.str();
return message;
}
virtual std::string getID() { return std::string(""); };
public:
Logger() = default;
virtual ~Logger() = default;
template <typename... Args>
std::string format_string(const std::string& format, Args... args) {
int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) +
1; // Extra space for '\0'
if (size_s <= 0) {
std::cout << "Error during formatting.";
return "";
}
auto size = static_cast<size_t>(size_s);
std::unique_ptr<char[]> buf(new char[size]);
std::snprintf(buf.get(), size, format.c_str(), args...);
return std::string(buf.get(),
buf.get() + size - 1); // We don't want the '\0' inside
}
// Templated log function to handle various data types and arguments
template <typename... Args>
void log(LogLevel_e log_level, Args... args) {
std::string message = handleInput(args...);
std::string logLevel = checkLogLevel(log_level);
std::string logMessage =
format_string("[%s - %s]: %s", logLevel.c_str(), this->getID().c_str(),
message.c_str());
std::cout << logMessage << '\n';
}
template <typename... Args>
void log(Args... args) {
std::string message = handleInput(args...);
std::string logLevel = checkLogLevel(LogLevel_e::INFO);
std::string logMessage =
Helpers::format_string("[%s - %s]: %s", logLevel.c_str(),
this->getID().c_str(), message.c_str());
std::cout << logMessage << '\n';
}
};
typedef Logger::LogLevel_e LogLevel_t;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment