forked from LMMS/lmms
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial implementation of the new logging mechanism. Implements the c…
- Loading branch information
1 parent
04239ba
commit 0d0c002
Showing
7 changed files
with
296 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#ifndef CONSOLE_LOG_SINK_H | ||
#define CONSOLE_LOG_SINK_H | ||
|
||
#include "Logging.h" | ||
|
||
class ConsoleLogSink: public LogSink | ||
{ | ||
public: | ||
ConsoleLogSink(LogVerbosity maxVerbosity, LogManager& logManager); | ||
void onLogLine(const LogLine& line) override; | ||
~ConsoleLogSink() = default; | ||
}; | ||
|
||
#endif // CONSOLE_LOG_SINK_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
#ifndef DEBUG_TRACE_H | ||
#define DEBUG_TRACE_H | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
class LogManager; | ||
|
||
enum class LogVerbosity | ||
{ | ||
Fatal = 0, | ||
Error, | ||
Warning, | ||
Info, | ||
Debug_Lo, | ||
Debug_Hi, | ||
|
||
Last | ||
}; | ||
|
||
struct LogLine | ||
{ | ||
LogVerbosity verbosity; | ||
unsigned int logLineNo; | ||
unsigned long int timestamp; | ||
std::string fileName; | ||
unsigned int fileLineNo; | ||
std::string content; | ||
|
||
LogLine(LogVerbosity verbosity, | ||
const char* fileName, | ||
unsigned int fileLineNo, | ||
const char* content); | ||
|
||
std::string toString() const; | ||
}; | ||
|
||
class LogSink | ||
{ | ||
public: | ||
LogSink(LogVerbosity maxVerbosity, LogManager& logManager); | ||
virtual ~LogSink(); | ||
|
||
virtual void onLogLine(const LogLine& line) = 0; | ||
|
||
LogVerbosity getMaxVerbosity() | ||
{ | ||
return m_maxVerbosity; | ||
} | ||
|
||
private: | ||
LogVerbosity m_maxVerbosity; | ||
LogManager& m_logManager; | ||
}; | ||
|
||
class LogManager | ||
{ | ||
public: | ||
static LogManager& inst(); | ||
~LogManager(); | ||
void addSink(LogSink* sink); | ||
|
||
void pauseFlush(); | ||
void resumeFlush(); | ||
|
||
void push(const LogLine& logLine); | ||
void flush(); | ||
|
||
private: | ||
LogManager(); | ||
|
||
bool m_flushPaused; | ||
LogVerbosity m_maxVerbosity; | ||
std::vector<LogSink*> m_sinks; | ||
std::vector<LogLine> m_pendingLogLines; | ||
}; | ||
|
||
#define Log_Gen(verb,format,...) \ | ||
do { \ | ||
char _content[1024]; \ | ||
snprintf(_content, sizeof(_content), format, ##__VA_ARGS__); \ | ||
LogLine _logLine(verb, __FILE__, __LINE__, _content); \ | ||
LogManager::inst().push(std::move(_logLine)); \ | ||
} while(0) | ||
|
||
#define Log_Fatal(format,...) Log_Gen(LogVerbosity::Fatal, format, ##__VA_ARGS__); | ||
#define Log_Err(format,...) Log_Gen(LogVerbosity::Error, format, ##__VA_ARGS__); | ||
#define Log_Wrn(format,...) Log_Gen(LogVerbosity::Warning, format, ##__VA_ARGS__); | ||
#define Log_Inf(format,...) Log_Gen(LogVerbosity::Info, format, ##__VA_ARGS__); | ||
#define Log_Dbg_Lo(format, ...) Log_Gen(LogVerbosity::Debug_Lo, format, ##__VA_ARGS__); | ||
#define Log_Dbg_Hi(format, ...) Log_Gen(LogVerbosity::Debug_Hi, format, ##__VA_ARGS__); | ||
|
||
#endif // DEBUG_TRACE_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#include <iostream> | ||
#include "ConsoleLogSink.h" | ||
|
||
ConsoleLogSink::ConsoleLogSink(LogVerbosity maxVerbosity, LogManager& logManager) | ||
: LogSink(maxVerbosity, logManager) | ||
{ | ||
} | ||
|
||
void ConsoleLogSink::onLogLine(const LogLine& line) | ||
{ | ||
std::cout << line.toString() << std::endl; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
#include "Logging.h" | ||
#include <sstream> | ||
#include <iomanip> | ||
#include <sys/time.h> | ||
|
||
const int LOG_QUEUE_SIZE = 256; | ||
const unsigned int USEC_PER_SEC = 1000000; | ||
|
||
#if defined(WIN32) || defined(_WIN32) | ||
#define PATH_SEPARATOR "\\" | ||
#else | ||
#define PATH_SEPARATOR "/" | ||
#endif | ||
|
||
|
||
LogLine::LogLine(LogVerbosity verbosity, | ||
const char* fileName, | ||
unsigned int fileLineNo, | ||
const char* content) | ||
{ | ||
static unsigned int logLineNo = 0; | ||
static unsigned long int initialTimestamp = 0; | ||
struct timeval tv; | ||
|
||
this->verbosity = verbosity; | ||
this->fileLineNo = fileLineNo; | ||
this->fileName = fileName; | ||
this->content = content; | ||
this->logLineNo = logLineNo++; | ||
|
||
/* Fill the timestamp information */ | ||
gettimeofday(&tv, nullptr); | ||
this->timestamp = tv.tv_sec * USEC_PER_SEC + tv.tv_usec; | ||
|
||
/* If the timestamp was not set yet, initialize it with the value | ||
* we have just obtained - this way the very first log line will | ||
* always have the timestamp of 0 */ | ||
if (initialTimestamp == 0) | ||
{ | ||
initialTimestamp = this->timestamp; | ||
} | ||
|
||
this->timestamp -= initialTimestamp; | ||
|
||
/* Check if the file name is a basename. If not, drop the directory | ||
* information */ | ||
if (this->fileName.find(PATH_SEPARATOR) != std::string::npos) | ||
{ | ||
this->fileName = this->fileName.substr( | ||
this->fileName.rfind(PATH_SEPARATOR)+1); | ||
} | ||
|
||
} | ||
|
||
std::string LogLine::toString() const | ||
{ | ||
const char VERBOSITY_LETTERS[] = {'F', 'E', 'W', 'I', 'L', 'H'}; | ||
static_assert(sizeof(VERBOSITY_LETTERS) == (int)LogVerbosity::Last); | ||
|
||
std::ostringstream os; | ||
if (verbosity < LogVerbosity::Last) | ||
{ | ||
os << VERBOSITY_LETTERS[(int)verbosity]; | ||
} | ||
else | ||
{ | ||
os << "X"; | ||
} | ||
|
||
os << "-" << logLineNo; | ||
os << "-" << (timestamp / USEC_PER_SEC); | ||
os << "." << std::setw(6) << std::setfill('0') << (timestamp % USEC_PER_SEC); | ||
os << "-" << fileName << ":" << fileLineNo; | ||
os << ": " << content; | ||
|
||
return os.str(); | ||
} | ||
|
||
LogSink::LogSink(LogVerbosity maxVerbosity, LogManager& logManager) | ||
: m_maxVerbosity(maxVerbosity), m_logManager(logManager) | ||
{ | ||
} | ||
|
||
LogSink::~LogSink() | ||
{ | ||
} | ||
|
||
|
||
LogManager& LogManager::inst() | ||
{ | ||
static LogManager instance; | ||
return instance; | ||
} | ||
|
||
LogManager::LogManager() | ||
{ | ||
m_pendingLogLines.reserve(LOG_QUEUE_SIZE); | ||
m_flushPaused = false; | ||
} | ||
|
||
LogManager::~LogManager() | ||
{ | ||
for (LogSink* pSink: m_sinks) | ||
{ | ||
delete pSink; | ||
} | ||
} | ||
|
||
void LogManager::addSink(LogSink* sink) | ||
{ | ||
m_sinks.push_back(sink); | ||
} | ||
|
||
void LogManager::pauseFlush() | ||
{ | ||
m_flushPaused = true; | ||
} | ||
|
||
void LogManager::resumeFlush() | ||
{ | ||
m_flushPaused = false; | ||
} | ||
|
||
void LogManager::push(const LogLine& logLine) | ||
{ | ||
if (m_maxVerbosity > logLine.verbosity) return; | ||
|
||
if (m_pendingLogLines.size() < LOG_QUEUE_SIZE -1) | ||
{ | ||
m_pendingLogLines.push_back(logLine); | ||
} | ||
else if (m_pendingLogLines.size() == LOG_QUEUE_SIZE - 1) | ||
{ | ||
Log_Wrn("Log queue overflow, some lines might be dropped"); | ||
} | ||
|
||
if (!m_flushPaused) flush(); | ||
} | ||
|
||
void LogManager::flush() | ||
{ | ||
for (LogSink* pSink: m_sinks) | ||
{ | ||
for (LogLine& logLine: m_pendingLogLines) | ||
{ | ||
if (logLine.verbosity <= pSink->getMaxVerbosity()) | ||
{ | ||
pSink->onLogLine(logLine); | ||
} | ||
} | ||
} | ||
m_pendingLogLines.clear(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters