Properly format multiline logs
As a side effect, colouring on Windows should now work regardless of version
This commit is contained in:
parent
2c171a9b02
commit
32f725d32f
|
@ -38,29 +38,29 @@
|
||||||
#define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes
|
#define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes
|
||||||
#define MAX_LOG_FILES 50
|
#define MAX_LOG_FILES 50
|
||||||
|
|
||||||
#define MCLOG_TYPE(level, cat, type, x) do { \
|
#define MCLOG_TYPE(level, cat, color, type, x) do { \
|
||||||
if (ELPP->vRegistry()->allowed(level, cat)) { \
|
if (ELPP->vRegistry()->allowed(level, cat)) { \
|
||||||
el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
|
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define MCLOG(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::NormalLog, x)
|
#define MCLOG(level, cat, color, x) MCLOG_TYPE(level, cat, color, el::base::DispatchAction::NormalLog, x)
|
||||||
#define MCLOG_FILE(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::FileOnlyLog, x)
|
#define MCLOG_FILE(level, cat, x) MCLOG_TYPE(level, cat, el::Color::Default, el::base::DispatchAction::FileOnlyLog, x)
|
||||||
|
|
||||||
#define MCFATAL(cat,x) MCLOG(el::Level::Fatal,cat, x)
|
#define MCFATAL(cat,x) MCLOG(el::Level::Fatal,cat, el::Color::Default, x)
|
||||||
#define MCERROR(cat,x) MCLOG(el::Level::Error,cat, x)
|
#define MCERROR(cat,x) MCLOG(el::Level::Error,cat, el::Color::Default, x)
|
||||||
#define MCWARNING(cat,x) MCLOG(el::Level::Warning,cat, x)
|
#define MCWARNING(cat,x) MCLOG(el::Level::Warning,cat, el::Color::Default, x)
|
||||||
#define MCINFO(cat,x) MCLOG(el::Level::Info,cat, x)
|
#define MCINFO(cat,x) MCLOG(el::Level::Info,cat, el::Color::Default, x)
|
||||||
#define MCDEBUG(cat,x) MCLOG(el::Level::Debug,cat, x)
|
#define MCDEBUG(cat,x) MCLOG(el::Level::Debug,cat, el::Color::Default, x)
|
||||||
#define MCTRACE(cat,x) MCLOG(el::Level::Trace,cat, x)
|
#define MCTRACE(cat,x) MCLOG(el::Level::Trace,cat, el::Color::Default, x)
|
||||||
|
|
||||||
#define MCLOG_COLOR(level,cat,color,x) MCLOG(level,cat,"\033[1;" color "m" << x << "\033[0m")
|
#define MCLOG_COLOR(level,cat,color,x) MCLOG(level,cat,color,x)
|
||||||
#define MCLOG_RED(level,cat,x) MCLOG_COLOR(level,cat,"31",x)
|
#define MCLOG_RED(level,cat,x) MCLOG_COLOR(level,cat,el::Color::Red,x)
|
||||||
#define MCLOG_GREEN(level,cat,x) MCLOG_COLOR(level,cat,"32",x)
|
#define MCLOG_GREEN(level,cat,x) MCLOG_COLOR(level,cat,el::Color::Green,x)
|
||||||
#define MCLOG_YELLOW(level,cat,x) MCLOG_COLOR(level,cat,"33",x)
|
#define MCLOG_YELLOW(level,cat,x) MCLOG_COLOR(level,cat,el::Color::Yellow,x)
|
||||||
#define MCLOG_BLUE(level,cat,x) MCLOG_COLOR(level,cat,"34",x)
|
#define MCLOG_BLUE(level,cat,x) MCLOG_COLOR(level,cat,el::Color::Blue,x)
|
||||||
#define MCLOG_MAGENTA(level,cat,x) MCLOG_COLOR(level,cat,"35",x)
|
#define MCLOG_MAGENTA(level,cat,x) MCLOG_COLOR(level,cat,el::Color::Magenta,x)
|
||||||
#define MCLOG_CYAN(level,cat,x) MCLOG_COLOR(level,cat,"36",x)
|
#define MCLOG_CYAN(level,cat,x) MCLOG_COLOR(level,cat,el::Color::Cyan,x)
|
||||||
|
|
||||||
#define MLOG_RED(level,x) MCLOG_RED(level,MONERO_DEFAULT_LOG_CATEGORY,x)
|
#define MLOG_RED(level,x) MCLOG_RED(level,MONERO_DEFAULT_LOG_CATEGORY,x)
|
||||||
#define MLOG_GREEN(level,x) MCLOG_GREEN(level,MONERO_DEFAULT_LOG_CATEGORY,x)
|
#define MLOG_GREEN(level,x) MCLOG_GREEN(level,MONERO_DEFAULT_LOG_CATEGORY,x)
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
#define MINFO(x) MCINFO(MONERO_DEFAULT_LOG_CATEGORY,x)
|
#define MINFO(x) MCINFO(MONERO_DEFAULT_LOG_CATEGORY,x)
|
||||||
#define MDEBUG(x) MCDEBUG(MONERO_DEFAULT_LOG_CATEGORY,x)
|
#define MDEBUG(x) MCDEBUG(MONERO_DEFAULT_LOG_CATEGORY,x)
|
||||||
#define MTRACE(x) MCTRACE(MONERO_DEFAULT_LOG_CATEGORY,x)
|
#define MTRACE(x) MCTRACE(MONERO_DEFAULT_LOG_CATEGORY,x)
|
||||||
#define MLOG(level,x) MCLOG(level,MONERO_DEFAULT_LOG_CATEGORY,x)
|
#define MLOG(level,x) MCLOG(level,MONERO_DEFAULT_LOG_CATEGORY,el::Color::Default,x)
|
||||||
|
|
||||||
#define MGINFO(x) MCINFO("global",x)
|
#define MGINFO(x) MCINFO("global",x)
|
||||||
#define MGINFO_RED(x) MCLOG_RED(el::Level::Info, "global",x)
|
#define MGINFO_RED(x) MCLOG_RED(el::Level::Info, "global",x)
|
||||||
|
@ -85,14 +85,14 @@
|
||||||
#define MGINFO_MAGENTA(x) MCLOG_MAGENTA(el::Level::Info, "global",x)
|
#define MGINFO_MAGENTA(x) MCLOG_MAGENTA(el::Level::Info, "global",x)
|
||||||
#define MGINFO_CYAN(x) MCLOG_CYAN(el::Level::Info, "global",x)
|
#define MGINFO_CYAN(x) MCLOG_CYAN(el::Level::Info, "global",x)
|
||||||
|
|
||||||
#define IFLOG(level, cat, type, init, x) \
|
#define IFLOG(level, cat, color, type, init, x) \
|
||||||
do { \
|
do { \
|
||||||
if (ELPP->vRegistry()->allowed(level, cat)) { \
|
if (ELPP->vRegistry()->allowed(level, cat)) { \
|
||||||
init; \
|
init; \
|
||||||
el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
|
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
#define MIDEBUG(init, x) IFLOG(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY, el::base::DispatchAction::NormalLog, init, x)
|
#define MIDEBUG(init, x) IFLOG(el::Level::Debug, MONERO_DEFAULT_LOG_CATEGORY, el::Color::Default, el::base::DispatchAction::NormalLog, init, x)
|
||||||
|
|
||||||
|
|
||||||
#define LOG_ERROR(x) MERROR(x)
|
#define LOG_ERROR(x) MERROR(x)
|
||||||
|
|
|
@ -109,7 +109,7 @@ static const char *get_default_categories(int level)
|
||||||
categories = "*:DEBUG";
|
categories = "*:DEBUG";
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
categories = "*:TRACE";
|
categories = "*:TRACE,*.dump:DEBUG";
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
categories = "*:TRACE";
|
categories = "*:TRACE";
|
||||||
|
@ -472,4 +472,40 @@ void reset_console_color() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mlog(el::Level level, const char *category, const char *format, va_list ap)
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
char *p = NULL;
|
||||||
|
va_list apc;
|
||||||
|
|
||||||
|
/* Determine required size */
|
||||||
|
va_copy(apc, ap);
|
||||||
|
size = vsnprintf(p, size, format, apc);
|
||||||
|
va_end(apc);
|
||||||
|
if (size < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size++; /* For '\0' */
|
||||||
|
p = (char*)malloc(size);
|
||||||
|
if (p == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
size = vsnprintf(p, size, format, ap);
|
||||||
|
if (size < 0)
|
||||||
|
{
|
||||||
|
free(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MCLOG(level, category, el::Color::Default, p);
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mfatal(const char *category, const char *fmt, ...) { va_list ap; va_start(ap, fmt); mlog(el::Level::Fatal, category, fmt, ap); va_end(ap); }
|
||||||
|
void merror(const char *category, const char *fmt, ...) { va_list ap; va_start(ap, fmt); mlog(el::Level::Error, category, fmt, ap); va_end(ap); }
|
||||||
|
void mwarning(const char *category, const char *fmt, ...) { va_list ap; va_start(ap, fmt); mlog(el::Level::Warning, category, fmt, ap); va_end(ap); }
|
||||||
|
void minfo(const char *category, const char *fmt, ...) { va_list ap; va_start(ap, fmt); mlog(el::Level::Info, category, fmt, ap); va_end(ap); }
|
||||||
|
void mdebug(const char *category, const char *fmt, ...) { va_list ap; va_start(ap, fmt); mlog(el::Level::Debug, category, fmt, ap); va_end(ap); }
|
||||||
|
void mtrace(const char *category, const char *fmt, ...) { va_list ap; va_start(ap, fmt); mlog(el::Level::Trace, category, fmt, ap); va_end(ap); }
|
||||||
|
|
||||||
#endif //_MLOG_H_
|
#endif //_MLOG_H_
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "easylogging++.h"
|
#include "easylogging++.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
|
||||||
#if defined(AUTO_INITIALIZE_EASYLOGGINGPP)
|
#if defined(AUTO_INITIALIZE_EASYLOGGINGPP)
|
||||||
INITIALIZE_EASYLOGGINGPP
|
INITIALIZE_EASYLOGGINGPP
|
||||||
|
@ -133,6 +134,50 @@ static void abort(int status, const std::string& reason) {
|
||||||
#endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG)
|
#endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static el::Color colorFromLevel(el::Level level)
|
||||||
|
{
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case Level::Error: case Level::Fatal: return el::Color::Red;
|
||||||
|
case Level::Warning: return el::Color::Yellow;
|
||||||
|
case Level::Debug: return el::Color::Green;
|
||||||
|
case Level::Info: return el::Color::Cyan;
|
||||||
|
case Level::Trace: return el::Color::Magenta;
|
||||||
|
default: return el::Color::Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setConsoleColor(el::Color color, bool bright)
|
||||||
|
{
|
||||||
|
#if ELPP_OS_WINDOWS
|
||||||
|
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
switch (color)
|
||||||
|
{
|
||||||
|
case el::Color::Red: SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | (bright ? FOREGROUND_INTENSITY:0)); break;
|
||||||
|
case el::Color::Green: SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY:0)); break;
|
||||||
|
case el::Color::Yellow: SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY:0)); break;
|
||||||
|
case el::Color::Blue: SetConsoleTextAttribute(h_stdout, FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0)); break;
|
||||||
|
case el::Color::Magenta: SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0)); break;
|
||||||
|
case el::Color::Cyan: SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0)); break;
|
||||||
|
case el::Color::Default: default: SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0)); break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
|
||||||
|
{
|
||||||
|
switch (color)
|
||||||
|
{
|
||||||
|
case el::Color::Red: ELPP_COUT << (bright ? "\033[1;31m" : "\033[0;31m"); break;
|
||||||
|
case el::Color::Green: ELPP_COUT << (bright ? "\033[1;32m" : "\033[0;32m"); break;
|
||||||
|
case el::Color::Yellow: ELPP_COUT << (bright ? "\033[1;33m" : "\033[0;33m"); break;
|
||||||
|
case el::Color::Blue: ELPP_COUT << (bright ? "\033[1;34m" : "\033[0;34m"); break;
|
||||||
|
case el::Color::Magenta: ELPP_COUT << (bright ? "\033[1;35m" : "\033[0;35m"); break;
|
||||||
|
case el::Color::Cyan: ELPP_COUT << (bright ? "\033[1;36m" : "\033[0;36m"); break;
|
||||||
|
case el::Color::Default: default: ELPP_COUT << "\033[0m"; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
} // namespace base
|
} // namespace base
|
||||||
|
|
||||||
|
@ -609,9 +654,23 @@ void Configurations::unsafeSetGlobally(ConfigurationType configurationType, cons
|
||||||
|
|
||||||
// LogBuilder
|
// LogBuilder
|
||||||
|
|
||||||
void LogBuilder::convertToColoredOutput(base::type::string_t* logLine, Level level) {
|
void LogBuilder::convertToColoredOutput(base::type::string_t* logLine, Level level, Color color) {
|
||||||
if (!m_termSupportsColor) return;
|
if (!m_termSupportsColor) return;
|
||||||
const base::type::char_t* resetColor = ELPP_LITERAL("\x1b[0m");
|
const base::type::char_t* resetColor = ELPP_LITERAL("\x1b[0m");
|
||||||
|
if (color == Color::Red)
|
||||||
|
*logLine = ELPP_LITERAL("\x1b[1;31m") + *logLine + resetColor;
|
||||||
|
else if (color == Color::Yellow)
|
||||||
|
*logLine = ELPP_LITERAL("\x1b[1;33m") + *logLine + resetColor;
|
||||||
|
else if (color == Color::Green)
|
||||||
|
*logLine = ELPP_LITERAL("\x1b[1;32m") + *logLine + resetColor;
|
||||||
|
else if (color == Color::Cyan)
|
||||||
|
*logLine = ELPP_LITERAL("\x1b[1;36m") + *logLine + resetColor;
|
||||||
|
else if (color == Color::Magenta)
|
||||||
|
*logLine = ELPP_LITERAL("\x1b[1;35m") + *logLine + resetColor;
|
||||||
|
else if (color == Color::Blue)
|
||||||
|
*logLine = ELPP_LITERAL("\x1b[1;34m") + *logLine + resetColor;
|
||||||
|
else if (color == Color::Default)
|
||||||
|
{
|
||||||
if (level == Level::Error || level == Level::Fatal)
|
if (level == Level::Error || level == Level::Fatal)
|
||||||
*logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor;
|
*logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor;
|
||||||
else if (level == Level::Warning)
|
else if (level == Level::Warning)
|
||||||
|
@ -622,6 +681,7 @@ void LogBuilder::convertToColoredOutput(base::type::string_t* logLine, Level lev
|
||||||
*logLine = ELPP_LITERAL("\x1b[36m") + *logLine + resetColor;
|
*logLine = ELPP_LITERAL("\x1b[36m") + *logLine + resetColor;
|
||||||
else if (level == Level::Trace)
|
else if (level == Level::Trace)
|
||||||
*logLine = ELPP_LITERAL("\x1b[35m") + *logLine + resetColor;
|
*logLine = ELPP_LITERAL("\x1b[35m") + *logLine + resetColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logger
|
// Logger
|
||||||
|
@ -2372,13 +2432,32 @@ void DefaultLogDispatchCallback::handle(const LogDispatchData* data) {
|
||||||
m_data = data;
|
m_data = data;
|
||||||
base::TypedConfigurations* tc = m_data->logMessage()->logger()->typedConfigurations();
|
base::TypedConfigurations* tc = m_data->logMessage()->logger()->typedConfigurations();
|
||||||
const base::LogFormat* logFormat = &tc->logFormat(m_data->logMessage()->level());
|
const base::LogFormat* logFormat = &tc->logFormat(m_data->logMessage()->level());
|
||||||
|
|
||||||
|
const auto &logmsg = m_data->logMessage();
|
||||||
|
const auto msg = logmsg->message();
|
||||||
|
if (strchr(msg.c_str(), '\n'))
|
||||||
|
{
|
||||||
|
std::vector<std::string> v;
|
||||||
|
boost::split(v, msg, boost::is_any_of("\n"));
|
||||||
|
for (const std::string &s: v)
|
||||||
|
{
|
||||||
|
LogMessage msgline(logmsg->level(), logmsg->color(), logmsg->file(), logmsg->line(), logmsg->func(), logmsg->verboseLevel(), logmsg->logger(), &s);
|
||||||
|
dispatch(base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(), &tc->subsecondPrecision(m_data->logMessage()->level())) + "\t" + convertToChar(m_data->logMessage()->level()) + " ",
|
||||||
|
s + "\n",
|
||||||
|
m_data->logMessage()->logger()->logBuilder()->build(&msgline,
|
||||||
|
m_data->dispatchAction() == base::DispatchAction::NormalLog || m_data->dispatchAction() == base::DispatchAction::FileOnlyLog));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
dispatch(base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(), &tc->subsecondPrecision(m_data->logMessage()->level()))
|
dispatch(base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(), &tc->subsecondPrecision(m_data->logMessage()->level()))
|
||||||
+ "\t" + convertToChar(m_data->logMessage()->level()) + " " + m_data->logMessage()->message() + "\n",
|
+ "\t" + convertToChar(m_data->logMessage()->level()) + " ", m_data->logMessage()->message() + "\n",
|
||||||
m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(),
|
m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(),
|
||||||
m_data->dispatchAction() == base::DispatchAction::NormalLog || m_data->dispatchAction() == base::DispatchAction::FileOnlyLog));
|
m_data->dispatchAction() == base::DispatchAction::NormalLog || m_data->dispatchAction() == base::DispatchAction::FileOnlyLog));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DefaultLogDispatchCallback::dispatch(base::type::string_t&& rawLine, base::type::string_t&& logLine) {
|
void DefaultLogDispatchCallback::dispatch(base::type::string_t&& rawLinePrefix, base::type::string_t&& rawLinePayload, base::type::string_t&& logLine) {
|
||||||
if (m_data->dispatchAction() == base::DispatchAction::NormalLog || m_data->dispatchAction() == base::DispatchAction::FileOnlyLog) {
|
if (m_data->dispatchAction() == base::DispatchAction::NormalLog || m_data->dispatchAction() == base::DispatchAction::FileOnlyLog) {
|
||||||
if (m_data->logMessage()->logger()->m_typedConfigurations->toFile(m_data->logMessage()->level())) {
|
if (m_data->logMessage()->logger()->m_typedConfigurations->toFile(m_data->logMessage()->level())) {
|
||||||
base::type::fstream_t* fs = m_data->logMessage()->logger()->m_typedConfigurations->fileStream(
|
base::type::fstream_t* fs = m_data->logMessage()->logger()->m_typedConfigurations->fileStream(
|
||||||
|
@ -2404,9 +2483,14 @@ void DefaultLogDispatchCallback::dispatch(base::type::string_t&& rawLine, base::
|
||||||
}
|
}
|
||||||
if (m_data->dispatchAction() != base::DispatchAction::FileOnlyLog) {
|
if (m_data->dispatchAction() != base::DispatchAction::FileOnlyLog) {
|
||||||
if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) {
|
if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) {
|
||||||
if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
|
const el::Level level = m_data->logMessage()->level();
|
||||||
m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&rawLine, m_data->logMessage()->level());
|
const el::Color color = m_data->logMessage()->color();
|
||||||
ELPP_COUT << ELPP_COUT_LINE(rawLine);
|
el::base::utils::setConsoleColor(el::base::utils::colorFromLevel(level), false);
|
||||||
|
ELPP_COUT << rawLinePrefix;
|
||||||
|
el::base::utils::setConsoleColor(color == el::Color::Default ? el::base::utils::colorFromLevel(level): color, color != el::Color::Default);
|
||||||
|
ELPP_COUT << rawLinePayload;
|
||||||
|
el::base::utils::setConsoleColor(el::Color::Default, false);
|
||||||
|
ELPP_COUT << std::flush;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2447,7 +2531,7 @@ void AsyncLogDispatchCallback::handle(const LogDispatchData* data) {
|
||||||
if ((data->dispatchAction() == base::DispatchAction::NormalLog || data->dispatchAction() == base::DispatchAction::FileOnlyLog)
|
if ((data->dispatchAction() == base::DispatchAction::NormalLog || data->dispatchAction() == base::DispatchAction::FileOnlyLog)
|
||||||
&& data->logMessage()->logger()->typedConfigurations()->toStandardOutput(data->logMessage()->level())) {
|
&& data->logMessage()->logger()->typedConfigurations()->toStandardOutput(data->logMessage()->level())) {
|
||||||
if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
|
if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput))
|
||||||
data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, data->logMessage()->level());
|
data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, data->logMessage()->level(), data->logMessage()->color());
|
||||||
ELPP_COUT << ELPP_COUT_LINE(logLine);
|
ELPP_COUT << ELPP_COUT_LINE(logLine);
|
||||||
}
|
}
|
||||||
// Save resources and only queue if we want to write to file otherwise just ignore handler
|
// Save resources and only queue if we want to write to file otherwise just ignore handler
|
||||||
|
@ -2739,7 +2823,7 @@ void Writer::initializeLogger(const std::string& loggerId, bool lookup, bool nee
|
||||||
ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId));
|
ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Writer(Level::Debug, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId)
|
Writer(Level::Debug, Color::Default, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId)
|
||||||
<< "Logger [" << loggerId << "] is not registered yet!";
|
<< "Logger [" << loggerId << "] is not registered yet!";
|
||||||
m_proceed = false;
|
m_proceed = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2813,7 +2897,7 @@ void Writer::processDispatch() {
|
||||||
void Writer::triggerDispatch(void) {
|
void Writer::triggerDispatch(void) {
|
||||||
if (m_proceed) {
|
if (m_proceed) {
|
||||||
if (m_msg == nullptr) {
|
if (m_msg == nullptr) {
|
||||||
LogMessage msg(m_level, m_file, m_line, m_func, m_verboseLevel,
|
LogMessage msg(m_level, m_color, m_file, m_line, m_func, m_verboseLevel,
|
||||||
m_logger);
|
m_logger);
|
||||||
base::LogDispatcher(m_proceed, &msg, m_dispatchAction).dispatch();
|
base::LogDispatcher(m_proceed, &msg, m_dispatchAction).dispatch();
|
||||||
} else {
|
} else {
|
||||||
|
@ -2826,7 +2910,7 @@ void Writer::triggerDispatch(void) {
|
||||||
}
|
}
|
||||||
if (m_proceed && m_level == Level::Fatal
|
if (m_proceed && m_level == Level::Fatal
|
||||||
&& !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) {
|
&& !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) {
|
||||||
base::Writer(Level::Warning, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId)
|
base::Writer(Level::Warning, Color::Default, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId)
|
||||||
<< "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]";
|
<< "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]";
|
||||||
std::stringstream reasonStream;
|
std::stringstream reasonStream;
|
||||||
reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]"
|
reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]"
|
||||||
|
|
|
@ -604,6 +604,15 @@ enum class Level : base::type::EnumType {
|
||||||
/// @brief Represents unknown level
|
/// @brief Represents unknown level
|
||||||
Unknown = 1010
|
Unknown = 1010
|
||||||
};
|
};
|
||||||
|
enum class Color : base::type::EnumType {
|
||||||
|
Default,
|
||||||
|
Red,
|
||||||
|
Green,
|
||||||
|
Yellow,
|
||||||
|
Blue,
|
||||||
|
Magenta,
|
||||||
|
Cyan,
|
||||||
|
};
|
||||||
} // namespace el
|
} // namespace el
|
||||||
namespace std {
|
namespace std {
|
||||||
template<> struct hash<el::Level> {
|
template<> struct hash<el::Level> {
|
||||||
|
@ -2225,7 +2234,7 @@ class LogBuilder : base::NoCopy {
|
||||||
ELPP_INTERNAL_INFO(3, "Destroying log builder...")
|
ELPP_INTERNAL_INFO(3, "Destroying log builder...")
|
||||||
}
|
}
|
||||||
virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0;
|
virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0;
|
||||||
void convertToColoredOutput(base::type::string_t* logLine, Level level);
|
void convertToColoredOutput(base::type::string_t* logLine, Level level, Color color);
|
||||||
private:
|
private:
|
||||||
bool m_termSupportsColor;
|
bool m_termSupportsColor;
|
||||||
friend class el::base::DefaultLogDispatchCallback;
|
friend class el::base::DefaultLogDispatchCallback;
|
||||||
|
@ -2503,14 +2512,17 @@ class VRegistry : base::NoCopy, public base::threading::ThreadSafe {
|
||||||
} // namespace base
|
} // namespace base
|
||||||
class LogMessage {
|
class LogMessage {
|
||||||
public:
|
public:
|
||||||
LogMessage(Level level, const std::string& file, base::type::LineNumber line, const std::string& func,
|
LogMessage(Level level, Color color, const std::string& file, base::type::LineNumber line, const std::string& func,
|
||||||
base::type::VerboseLevel verboseLevel, Logger* logger) :
|
base::type::VerboseLevel verboseLevel, Logger* logger, const base::type::string_t *msg = nullptr) :
|
||||||
m_level(level), m_file(file), m_line(line), m_func(func),
|
m_level(level), m_color(color), m_file(file), m_line(line), m_func(func),
|
||||||
m_verboseLevel(verboseLevel), m_logger(logger), m_message(logger->stream().str()) {
|
m_verboseLevel(verboseLevel), m_logger(logger), m_message(msg ? *msg : logger->stream().str()) {
|
||||||
}
|
}
|
||||||
inline Level level(void) const {
|
inline Level level(void) const {
|
||||||
return m_level;
|
return m_level;
|
||||||
}
|
}
|
||||||
|
inline Color color(void) const {
|
||||||
|
return m_color;
|
||||||
|
}
|
||||||
inline const std::string& file(void) const {
|
inline const std::string& file(void) const {
|
||||||
return m_file;
|
return m_file;
|
||||||
}
|
}
|
||||||
|
@ -2531,6 +2543,7 @@ class LogMessage {
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
Level m_level;
|
Level m_level;
|
||||||
|
Color m_color;
|
||||||
std::string m_file;
|
std::string m_file;
|
||||||
base::type::LineNumber m_line;
|
base::type::LineNumber m_line;
|
||||||
std::string m_func;
|
std::string m_func;
|
||||||
|
@ -2781,7 +2794,7 @@ class DefaultLogDispatchCallback : public LogDispatchCallback {
|
||||||
void handle(const LogDispatchData* data);
|
void handle(const LogDispatchData* data);
|
||||||
private:
|
private:
|
||||||
const LogDispatchData* m_data;
|
const LogDispatchData* m_data;
|
||||||
void dispatch(base::type::string_t&& rawLine, base::type::string_t&& logLine);
|
void dispatch(base::type::string_t&& rawLinePrefix, base::type::string_t&& rawLinePayload, base::type::string_t&& logLine);
|
||||||
};
|
};
|
||||||
#if ELPP_ASYNC_LOGGING
|
#if ELPP_ASYNC_LOGGING
|
||||||
class AsyncLogDispatchCallback : public LogDispatchCallback {
|
class AsyncLogDispatchCallback : public LogDispatchCallback {
|
||||||
|
@ -3242,10 +3255,10 @@ class NullWriter : base::NoCopy {
|
||||||
/// @brief Main entry point of each logging
|
/// @brief Main entry point of each logging
|
||||||
class Writer : base::NoCopy {
|
class Writer : base::NoCopy {
|
||||||
public:
|
public:
|
||||||
Writer(Level level, const char* file, base::type::LineNumber line,
|
Writer(Level level, Color color, const char* file, base::type::LineNumber line,
|
||||||
const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog,
|
const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog,
|
||||||
base::type::VerboseLevel verboseLevel = 0) :
|
base::type::VerboseLevel verboseLevel = 0) :
|
||||||
m_msg(nullptr), m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel),
|
m_msg(nullptr), m_level(level), m_color(color), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel),
|
||||||
m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) {
|
m_logger(nullptr), m_proceed(false), m_dispatchAction(dispatchAction) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3299,6 +3312,7 @@ class Writer : base::NoCopy {
|
||||||
protected:
|
protected:
|
||||||
LogMessage* m_msg;
|
LogMessage* m_msg;
|
||||||
Level m_level;
|
Level m_level;
|
||||||
|
Color m_color;
|
||||||
const char* m_file;
|
const char* m_file;
|
||||||
const base::type::LineNumber m_line;
|
const base::type::LineNumber m_line;
|
||||||
const char* m_func;
|
const char* m_func;
|
||||||
|
@ -3317,10 +3331,10 @@ class Writer : base::NoCopy {
|
||||||
};
|
};
|
||||||
class PErrorWriter : public base::Writer {
|
class PErrorWriter : public base::Writer {
|
||||||
public:
|
public:
|
||||||
PErrorWriter(Level level, const char* file, base::type::LineNumber line,
|
PErrorWriter(Level level, Color color, const char* file, base::type::LineNumber line,
|
||||||
const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog,
|
const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog,
|
||||||
base::type::VerboseLevel verboseLevel = 0) :
|
base::type::VerboseLevel verboseLevel = 0) :
|
||||||
base::Writer(level, file, line, func, dispatchAction, verboseLevel) {
|
base::Writer(level, color, file, line, func, dispatchAction, verboseLevel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~PErrorWriter(void);
|
virtual ~PErrorWriter(void);
|
||||||
|
@ -3353,14 +3367,14 @@ template <typename T>
|
||||||
void Logger::log_(Level level, int vlevel, const T& log) {
|
void Logger::log_(Level level, int vlevel, const T& log) {
|
||||||
if (level == Level::Verbose) {
|
if (level == Level::Verbose) {
|
||||||
if (ELPP->vRegistry()->allowed(vlevel, __FILE__)) {
|
if (ELPP->vRegistry()->allowed(vlevel, __FILE__)) {
|
||||||
base::Writer(Level::Verbose, "FILE", 0, "FUNCTION",
|
base::Writer(Level::Verbose, Color::Default, "FILE", 0, "FUNCTION",
|
||||||
base::DispatchAction::NormalLog, vlevel).construct(this, false) << log;
|
base::DispatchAction::NormalLog, vlevel).construct(this, false) << log;
|
||||||
} else {
|
} else {
|
||||||
stream().str(ELPP_LITERAL(""));
|
stream().str(ELPP_LITERAL(""));
|
||||||
releaseLock();
|
releaseLock();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log;
|
base::Writer(level, Color::Default, "FILE", 0, "FUNCTION").construct(this, false) << log;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
|
@ -3460,18 +3474,18 @@ LOGGER_LEVEL_WRITERS_DISABLED(trace, Level::Trace)
|
||||||
#endif // ELPP_COMPILER_MSVC
|
#endif // ELPP_COMPILER_MSVC
|
||||||
#define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
|
#define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
|
||||||
#define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \
|
#define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \
|
||||||
writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
writer(level, el::Color::Default, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
||||||
#define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) if (condition) \
|
#define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) if (condition) \
|
||||||
writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
writer(level, el::Color::Default, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
||||||
#define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \
|
#define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \
|
||||||
ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion) && \
|
ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion) && \
|
||||||
writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
writer(level, el::Color::Default, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
||||||
#define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \
|
#define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \
|
||||||
ELPP->validateAfterNCounter(__FILE__, __LINE__, n) && \
|
ELPP->validateAfterNCounter(__FILE__, __LINE__, n) && \
|
||||||
writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
writer(level, el::Color::Default, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
||||||
#define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \
|
#define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \
|
||||||
ELPP->validateNTimesCounter(__FILE__, __LINE__, n) && \
|
ELPP->validateNTimesCounter(__FILE__, __LINE__, n) && \
|
||||||
writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
writer(level, el::Color::Default, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__)
|
||||||
#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING)
|
#if defined(ELPP_FEATURE_ALL) || defined(ELPP_FEATURE_PERFORMANCE_TRACKING)
|
||||||
class PerformanceTrackingData {
|
class PerformanceTrackingData {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#define MONERO_DEFAULT_LOG_CATEGORY "perf"
|
#define MONERO_DEFAULT_LOG_CATEGORY "perf"
|
||||||
|
|
||||||
#define PERF_LOG_ALWAYS(level, cat, x) \
|
#define PERF_LOG_ALWAYS(level, cat, x) \
|
||||||
el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::FileOnlyLog).construct(cat) << x
|
el::base::Writer(level, el::Color::Default, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::FileOnlyLog).construct(cat) << x
|
||||||
#define PERF_LOG(level, cat, x) \
|
#define PERF_LOG(level, cat, x) \
|
||||||
do { \
|
do { \
|
||||||
if (ELPP->vRegistry()->allowed(level, cat)) PERF_LOG_ALWAYS(level, cat, x); \
|
if (ELPP->vRegistry()->allowed(level, cat)) PERF_LOG_ALWAYS(level, cat, x); \
|
||||||
|
|
|
@ -1641,7 +1641,7 @@ namespace cryptonote
|
||||||
break;
|
break;
|
||||||
case HardFork::UpdateNeeded:
|
case HardFork::UpdateNeeded:
|
||||||
level = el::Level::Info;
|
level = el::Level::Info;
|
||||||
MCLOG(level, "global", "Last scheduled hard fork time suggests a daemon update will be released within the next couple months.");
|
MCLOG(level, "global", el::Color::Default, "Last scheduled hard fork time suggests a daemon update will be released within the next couple months.");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
if (ELPP->vRegistry()->allowed(level, cat)) { \
|
if (ELPP->vRegistry()->allowed(level, cat)) { \
|
||||||
init; \
|
init; \
|
||||||
if (test) \
|
if (test) \
|
||||||
el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(cat) << x; \
|
el::base::Writer(level, el::Color::Default, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct(cat) << x; \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
@ -370,7 +370,7 @@ namespace cryptonote
|
||||||
uint64_t max_block_height = std::max(hshd.current_height,m_core.get_current_blockchain_height());
|
uint64_t max_block_height = std::max(hshd.current_height,m_core.get_current_blockchain_height());
|
||||||
uint64_t last_block_v1 = m_core.get_nettype() == TESTNET ? 624633 : m_core.get_nettype() == MAINNET ? 1009826 : (uint64_t)-1;
|
uint64_t last_block_v1 = m_core.get_nettype() == TESTNET ? 624633 : m_core.get_nettype() == MAINNET ? 1009826 : (uint64_t)-1;
|
||||||
uint64_t diff_v2 = max_block_height > last_block_v1 ? std::min(abs_diff, max_block_height - last_block_v1) : 0;
|
uint64_t diff_v2 = max_block_height > last_block_v1 ? std::min(abs_diff, max_block_height - last_block_v1) : 0;
|
||||||
MCLOG(is_inital ? el::Level::Info : el::Level::Debug, "global", context << "Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
|
MCLOG(is_inital ? el::Level::Info : el::Level::Debug, "global", el::Color::Yellow, context << "Sync data returned a new top block candidate: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
|
||||||
<< " [Your node is " << abs_diff << " blocks (" << ((abs_diff - diff_v2) / (24 * 60 * 60 / DIFFICULTY_TARGET_V1)) + (diff_v2 / (24 * 60 * 60 / DIFFICULTY_TARGET_V2)) << " days) "
|
<< " [Your node is " << abs_diff << " blocks (" << ((abs_diff - diff_v2) / (24 * 60 * 60 / DIFFICULTY_TARGET_V1)) + (diff_v2 / (24 * 60 * 60 / DIFFICULTY_TARGET_V2)) << " days) "
|
||||||
<< (0 <= diff ? std::string("behind") : std::string("ahead"))
|
<< (0 <= diff ? std::string("behind") : std::string("ahead"))
|
||||||
<< "] " << ENDL << "SYNCHRONIZATION started");
|
<< "] " << ENDL << "SYNCHRONIZATION started");
|
||||||
|
|
|
@ -178,3 +178,20 @@ TEST(logging, last_precedence)
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(logging, multiline)
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
mlog_set_categories("global:INFO");
|
||||||
|
MGINFO("first\nsecond\nthird");
|
||||||
|
std::string str;
|
||||||
|
ASSERT_TRUE(load_log_to_string(log_filename, str));
|
||||||
|
ASSERT_TRUE(nlines(str) == 3);
|
||||||
|
ASSERT_TRUE(str.find("global") != std::string::npos);
|
||||||
|
ASSERT_TRUE(str.find("first") != std::string::npos);
|
||||||
|
ASSERT_TRUE(str.find("second") != std::string::npos);
|
||||||
|
ASSERT_TRUE(str.find("third") != std::string::npos);
|
||||||
|
ASSERT_TRUE(str.find("first\nsecond") == std::string::npos);
|
||||||
|
ASSERT_TRUE(str.find("second\nthird") == std::string::npos);
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue