-
Notifications
You must be signed in to change notification settings - Fork 1
Simple Logger #30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simple Logger #30
Changes from all commits
cce957f
1e0b767
a5d8520
69855fb
5959b5a
c5a1469
a7830d5
2f940ae
77b54fb
d17c12c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** | ||
* @file Logger.cpp | ||
* @author Anand Doshi | ||
* @date 2025-01-08 | ||
* | ||
* @copyright Copyright (c) 2025 | ||
* | ||
*/ | ||
|
||
|
||
#include "Logger.hpp" | ||
#include "Exceptions.hpp" | ||
#include <cstdio> | ||
#include <ctime> | ||
#include <iterator> | ||
#include <stdexcept> | ||
#include <string> | ||
#include <string_view> | ||
|
||
bool Logger::isLoggable(Level level) | ||
{ | ||
if (filter == Filter::quiet) | ||
{ | ||
return false; | ||
} | ||
|
||
if (filter == Filter::important) | ||
{ | ||
return level == Level::error || level == Level::warning || level == Level::severe; | ||
} | ||
|
||
if (filter == Filter::verbose) | ||
{ | ||
return true; | ||
} | ||
|
||
return true; // unknown filter, everything logged | ||
} | ||
|
||
constexpr std::string_view Logger::getLevelName(Logger::Level level) | ||
{ | ||
switch (level) | ||
{ | ||
case Logger::Level::error: | ||
return "error"; | ||
case Logger::Level::warning: | ||
return "warning"; | ||
case Logger::Level::severe: | ||
return "severe"; | ||
case Logger::Level::info: | ||
return "info"; | ||
case Logger::Level::fine: | ||
return "fine"; | ||
case Logger::Level::debug: | ||
return "debug"; | ||
default: | ||
ThrowException("Invalid Level enum."); | ||
} | ||
} | ||
|
||
void Logger::log(Level level, const char *file, unsigned int line, const char *func, std::string_view message) | ||
{ | ||
if (!isLoggable(level)) | ||
return; | ||
|
||
std::time_t now = std::time(nullptr); | ||
|
||
char timestamp[std::size(Logger::timestampFormat)]; | ||
std::strftime(timestamp, std::size(Logger::timestampFormat), | ||
"%FT%TZ", std::localtime(&now)); | ||
|
||
char outputInfo[1024]; | ||
snprintf(outputInfo, 1024, "[%s](%s)[%s]@%s:%d:%s() ", timestamp, name.c_str(), getLevelName(level).data(), file, line, func); | ||
logStream << outputInfo << message << '\n'; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/** | ||
* @file Logger.hpp | ||
* @author Anand Doshi | ||
* @date 2025-01-08 | ||
* | ||
* @copyright Copyright (c) 2025 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've done some more thinking. I think the logger should be a singleton. We need an instance() public method and the constructor should be protected to prevent initialisation by the user. Then the info, error, ... methods become static methods calling instance().log(...) |
||
* | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <iostream> | ||
EdwardPalmer99 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#include <string_view> | ||
|
||
class Logger | ||
{ | ||
public: | ||
enum class Filter | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the Filter is overkill. Personally, I would just use a second Level variable. Then you can compare the level of the message being passed in to the level of our Level variable since enum values are just increasing integers. |
||
quiet, | ||
verbose, | ||
important | ||
}; | ||
|
||
enum class Level | ||
{ | ||
debug, | ||
fine, | ||
info, | ||
severe, | ||
warning, | ||
error | ||
}; | ||
|
||
EdwardPalmer99 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Logger(std::string_view name) | ||
: Logger{name, Filter::important, std::cout} | ||
{ | ||
} | ||
|
||
Logger(std::string_view name, Filter filter) | ||
: Logger{name, filter, std::cout} | ||
{ | ||
} | ||
|
||
Logger(std::string_view name, Filter filter, std::ostream &logStream) | ||
: name{name}, filter{filter}, logStream{logStream} | ||
{ | ||
} | ||
|
||
Logger() = delete; | ||
|
||
void log(Level level, const char *file, unsigned int line, const char *func, std::string_view message); | ||
|
||
inline void error(const char *file, unsigned int line, const char *func, std::string_view message) { log(Level::error, file, line, func, message); }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks a little messy doesn't it? I think specifying the file, line, func was a mistake on my part. Also probably overkill on the log options: [debug, info, warning, error] are enough I think |
||
inline void warning(const char *file, unsigned int line, const char *func, std::string_view message) { log(Level::warning, file, line, func, message); }; | ||
inline void severe(const char *file, unsigned int line, const char *func, std::string_view message) { log(Level::severe, file, line, func, message); }; | ||
inline void info(const char *file, unsigned int line, const char *func, std::string_view message) { log(Level::info, file, line, func, message); }; | ||
inline void fine(const char *file, unsigned int line, const char *func, std::string_view message) { log(Level::fine, file, line, func, message); }; | ||
inline void debug(const char *file, unsigned int line, const char *func, std::string_view message) { log(Level::debug, file, line, func, message); }; | ||
|
||
private: | ||
const std::string name; | ||
const Filter filter; | ||
std::ostream &logStream; | ||
|
||
// ISO 8601 date time format | ||
inline static const std::string timestampFormat{"yyyy-mm-ddThh:mm:ssZ"}; | ||
|
||
bool isLoggable(Level level); | ||
|
||
static constexpr std::string_view getLevelName(Level level); | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.