Skip to content

Instantly share code, notes, and snippets.

@nickelpro
Created December 21, 2021 04:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nickelpro/d3eb1395c55621bf5547825d57777b5b to your computer and use it in GitHub Desktop.
Save nickelpro/d3eb1395c55621bf5547825d57777b5b to your computer and use it in GitHub Desktop.
Logger from my last project
#include "logger.hpp"
vea::Logger VEA_SIMPLE_LOGGER;
namespace vea {
const char* lvl_strings[] {"trace", "debug", "info", "warn", "fatal"};
Logger::Logger(const std::string& name) : name(name) {}
Logger::Logger(const std::string& name, LogLevel lvl)
: name(name), logLvl(lvl), msgLvl(lvl) {}
Logger::Logger(const std::string& name, std::ostream& os)
: name(name), os(os) {}
Logger::Logger(const std::string& name, LogLevel lvl, std::ostream& os)
: name(name), logLvl(lvl), msgLvl(lvl), os(os) {}
Logger& Logger::operator<<(std::ostream& (*fn)(std::ostream&) ) {
if(msgLvl >= logLvl)
os << fn;
return *this;
}
Logger& Logger::operator()(LogLevel msgLvl) {
Logger::msgLvl = msgLvl;
return *this;
}
Logger& Logger::operator()(const char* file, int line, LogLevel msglvl) {
Logger::msgLvl = msglvl;
if(msgLvl >= logLvl) {
if(fmt & NAME)
os << name << ": ";
if(fmt & (FILE | LINE)) {
os << "[";
if(fmt & FILE) {
os << file;
if(fmt & LINE)
os << ":" << line << "]";
} else {
os << line << "]";
}
if(fmt & LEVEL)
os << " " << lvl_strings[msgLvl] << ": ";
} else if(fmt & LEVEL) {
os << lvl_strings[msgLvl] << ": ";
}
}
return *this;
}
Logger::LogLevel Logger::level() {
return logLvl;
}
void Logger::level(LogLevel logLvl) {
Logger::logLvl = logLvl;
}
std::string Logger::progName() {
return name;
}
void Logger::progName(const std::string& name) {
Logger::name = name;
}
int Logger::format() {
return fmt;
}
void Logger::format(int fmt) {
Logger::fmt = fmt;
}
} // namespace vea
#ifndef VEA_LOGGER_HPP
#define VEA_LOGGER_HPP
#include <iostream>
namespace vea {
/**
* @brief General Purpose Logging
*
* @note Typical usage:
* #define USE_VEA_SIMPLE_LOG
* #include "logger.h"
*
* LOG(debug) << "This is a debug message" << std::endl;
* SET_LOGLEVEL(warn);
* LOG(info) << "INFO is below WARN and won't be logged" << std::endl;
* SET_LOGFORMAT(LOG_LVL | LOG_FILE | LOG_LINE);
* LOG(fatal) << "This will print the lvl/file/line info too" << std::endl;
* LOG_INLINE(fatal) << "This won't print the format info" << std::endl;
*/
class Logger {
public:
enum LogLevel { TRACE, DEBUG, INFO, WARN, FATAL, MAX_LOG_LVL };
enum Format { NAME = 0x01, LEVEL = 0x02, FILE = 0x04, LINE = 0x08 };
Logger() = default;
/**
* @param name: name of the program
*/
Logger(const std::string& name);
/**
* @param name: name of the program
* @param lvl: minimum level for messages to be printed
*/
Logger(const std::string& name, LogLevel lvl);
/**
* @param name: name of the program
* @param os: target stream for messages
*/
Logger(const std::string& name, std::ostream& os);
/**
* @param name: name of the program
* @param lvl: minimum level for messages to be printed
* @param os: target stream for messages
*/
Logger(const std::string& name, LogLevel lvl, std::ostream& os);
/**
* @brief Print message
*
* @param msg: message to be printed
*
* @returns The Logger
*/
Logger& operator<<(const auto& msg) {
if(msgLvl >= logLvl)
os << msg;
return *this;
}
/**
* @brief Apply stream modifier
*
* @param fn: the stream modifier
*
* @returns The Logger
*/
Logger& operator<<(std::ostream& (*fn)(std::ostream&) );
/**
* @brief Sets the message log level
*
* @param msgLvl: new message level
*
* @returns The Logger
*/
Logger& operator()(LogLevel msgLvl);
/**
* @brief Sets the message log level and prints the message title
*
* @param file: current file, typically __FILE__ macro
* @param line: current line, typically __LINE__ macro
* @param msgLvl: new message level
*
* @returns The Logger
*/
Logger& operator()(const char* file, int line, LogLevel msgLvl);
/**
* @brief Gets the minimum log level
*
* @returns The minimum log level
*/
LogLevel level();
/**
* @brief Sets the minimum log level
*
* @param logLvl: new minimum log level
*/
void level(LogLevel logLvl);
/**
* @brief Gets the program name
*
* @returns The program name
*/
std::string progName();
/**
* @brief Sets the program name
*
* @param name: new program name
*/
void progName(const std::string& name);
/**
* @brief Gets the title format
*
* @returns The title format
*/
int format();
/**
* @brief Sets the title format, ex. Logger::LEVEL | Logger::FILE
*
* @param fmt: new title format
*/
void format(int fmt);
private:
std::string name {"vealog"};
LogLevel logLvl {DEBUG};
LogLevel msgLvl {DEBUG};
int fmt {NAME | LEVEL};
std::ostream& os {std::cerr};
};
// Another, "This would be a constexpr but we have to use C++14" moment
extern const char* lvl_strings[Logger::MAX_LOG_LVL];
} // namespace vea
#ifdef USE_VEA_SIMPLE_LOGGER
extern vea::Logger VEA_SIMPLE_LOGGER;
#define LOG(level) VEA_SIMPLE_LOGGER(__FILE__, __LINE__, level)
#define LOG_INLINE(level) VEA_SIMPLE_LOGGER(level)
#define SET_LOGLEVEL(new_level) VEA_SIMPLE_LOGGER.level(new_level)
#define SET_LOGNAME(name) VEA_SIMPLE_LOGGER.progName(name)
#define SET_LOGFORMAT(format) VEA_SIMPLE_LOGGER.format(format)
#define trace vea::Logger::TRACE
#define debug vea::Logger::DEBUG
#define info vea::Logger::INFO
#define warn vea::Logger::WARN
#define fatal vea::Logger::FATAL
#define LOG_LVL vea::Logger::LEVEL
#define LOG_LINE vea::Logger::LINE
#define LOG_FILE vea::Logger::FILE
#endif // USE_VEA_SIMPLE_LOGGER
#endif // VEA_LOGGER_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment