Update Log class.

This commit is contained in:
XMRig 2022-06-10 02:15:10 +07:00
parent d6a1c98314
commit 774f630e14
No known key found for this signature in database
GPG key ID: 446A53638BE94409
2 changed files with 202 additions and 121 deletions

View file

@ -1,7 +1,7 @@
/* XMRig
* Copyright (c) 2019 Spudz76 <https://github.com/Spudz76>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2022 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2022 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -15,9 +15,16 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*/
#ifdef WIN32
#ifdef XMRIG_OS_WIN
# include <winsock2.h>
# include <windows.h>
#endif
@ -25,40 +32,149 @@
#include <algorithm>
#include <cassert>
#include <cstdarg>
#include <cstring>
#include <ctime>
#include <mutex>
#include <string>
#include <uv.h>
#include <vector>
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/ILogBackend.h"
#include "base/tools/Chrono.h"
#include "base/tools/Object.h"
#ifdef XMRIG_FEATURE_EVENTS
# include "base/kernel/Events.h"
# include "base/kernel/events/LogEvent.h"
# include "base/kernel/private/LogConfig.h"
# include "base/kernel/Process.h"
#else
# include "base/kernel/interfaces/ILogBackend.h"
#endif
namespace xmrig {
bool Log::m_background = false;
bool Log::m_colors = true;
LogPrivate *Log::d = nullptr;
uint32_t Log::m_verbose = 0;
static char buf[Log::kMaxBufferSize]{};
static std::mutex mutex;
static const char *colors_map[] = {
RED_BOLD_S, // EMERG
RED_BOLD_S, // ALERT
RED_BOLD_S, // CRIT
RED_S, // ERR
YELLOW_S, // WARNING
WHITE_BOLD_S, // NOTICE
nullptr, // INFO
# ifdef WIN32
BLACK_BOLD_S // DEBUG
RED_BOLD_S "E ", // EMERG
RED_BOLD_S "A ", // ALERT
RED_BOLD_S "C ", // CRIT
RED_S "E ", // ERR
YELLOW_S "W ", // WARNING
WHITE_BOLD_S "N ", // NOTICE
"I ", // INFO
"1 ", // V1
"2 ", // V2
"3 ", // V3
"4 ", // V4
# ifdef XMRIG_OS_WIN
BLACK_BOLD_S "5 ", // V5
BLACK_BOLD_S "D " // DEBUG
# else
BRIGHT_BLACK_S // DEBUG
BRIGHT_BLACK_S "5 ", // V5
BRIGHT_BLACK_S "D " // DEBUG
# endif
};
static void log_endl(size_t &size)
{
# ifdef XMRIG_OS_WIN
memcpy(buf + size, CLEAR "\r\n", 7);
size += 6;
# else
memcpy(buf + size, CLEAR "\n", 6);
size += 5;
# endif
}
static void log_color(Log::Level level, size_t &size)
{
if (level == Log::NONE) {
return;
}
const char *color = colors_map[level];
if (color == nullptr) {
return;
}
const size_t s = strlen(color);
memcpy(buf + size, color, s); // NOLINT(bugprone-not-null-terminated-result)
size += s;
}
static uint64_t log_timestamp(Log::Level level, size_t &size, size_t &offset)
{
const uint64_t ms = Chrono::currentMSecsSinceEpoch();
if (level == Log::NONE) {
return ms;
}
time_t now = ms / 1000;
tm stime{};
# ifdef XMRIG_OS_WIN
localtime_s(&stime, &now);
# else
localtime_r(&now, &stime);
# endif
const int rc = snprintf(buf, sizeof(buf) - 1, "[%d-%02d-%02d %02d:%02d:%02d" BLACK_BOLD(".%03d") "] ",
stime.tm_year + 1900,
stime.tm_mon + 1,
stime.tm_mday,
stime.tm_hour,
stime.tm_min,
stime.tm_sec,
static_cast<int>(ms % 1000)
);
if (rc > 0) {
size = offset = static_cast<size_t>(rc);
}
return ms;
}
#ifdef XMRIG_FEATURE_EVENTS
static void log_print(Log::Level level, const char *fmt, va_list args)
{
size_t size = 0;
size_t offset = 0;
std::lock_guard<std::mutex> lock(mutex);
const uint64_t ts = log_timestamp(level, size, offset);
log_color(level, size);
const int rc = vsnprintf(buf + size, sizeof(buf) - offset - 32, fmt, args);
if (rc < 0) {
return;
}
size += std::min(static_cast<size_t>(rc), sizeof(buf) - offset - 32);
log_endl(size);
Process::events().post<LogEvent>(ts, level, buf, offset, size);
}
#else
class LogPrivate
{
public:
@ -70,46 +186,43 @@ public:
inline ~LogPrivate()
{
for (auto backend : m_backends) {
for (auto backend : backends) {
delete backend;
}
}
inline void add(ILogBackend *backend) { m_backends.push_back(backend); }
void print(Log::Level level, const char *fmt, va_list args)
{
size_t size = 0;
size_t offset = 0;
std::lock_guard<std::mutex> lock(m_mutex);
std::lock_guard<std::mutex> lock(mutex);
if (Log::isBackground() && m_backends.empty()) {
if (Log::isBackground() && backends.empty()) {
return;
}
const uint64_t ts = timestamp(level, size, offset);
color(level, size);
const uint64_t ts = log_timestamp(level, size, offset);
log_color(level, size);
const int rc = vsnprintf(m_buf + size, sizeof (m_buf) - offset - 32, fmt, args);
const int rc = vsnprintf(buf + size, sizeof (buf) - offset - 32, fmt, args);
if (rc < 0) {
return;
}
size += std::min(static_cast<size_t>(rc), sizeof (m_buf) - offset - 32);
endl(size);
size += std::min(static_cast<size_t>(rc), sizeof (buf) - offset - 32);
log_endl(size);
std::string txt(m_buf);
std::string txt(buf);
size_t i = 0;
while ((i = txt.find(CSI)) != std::string::npos) {
txt.erase(i, txt.find('m', i) - i + 1);
}
if (!m_backends.empty()) {
for (auto backend : m_backends) {
backend->print(ts, level, m_buf, offset, size, true);
if (!backends.empty()) {
for (auto backend : backends) {
backend->print(ts, level, buf, offset, size, true);
backend->print(ts, level, txt.c_str(), offset ? (offset - 11) : 0, txt.size(), false);
}
}
@ -120,94 +233,21 @@ public:
}
private:
inline uint64_t timestamp(Log::Level level, size_t &size, size_t &offset)
{
const uint64_t ms = Chrono::currentMSecsSinceEpoch();
if (level == Log::NONE) {
return ms;
}
time_t now = ms / 1000;
tm stime{};
# ifdef _WIN32
localtime_s(&stime, &now);
# else
localtime_r(&now, &stime);
# endif
const int rc = snprintf(m_buf, sizeof(m_buf) - 1, "[%d-%02d-%02d %02d:%02d:%02d" BLACK_BOLD(".%03d") "] ",
stime.tm_year + 1900,
stime.tm_mon + 1,
stime.tm_mday,
stime.tm_hour,
stime.tm_min,
stime.tm_sec,
static_cast<int>(ms % 1000)
);
if (rc > 0) {
size = offset = static_cast<size_t>(rc);
}
return ms;
}
inline void color(Log::Level level, size_t &size)
{
if (level == Log::NONE) {
return;
}
const char *color = colors_map[level];
if (color == nullptr) {
return;
}
const size_t s = strlen(color);
memcpy(m_buf + size, color, s);
size += s;
}
inline void endl(size_t &size)
{
# ifdef _WIN32
memcpy(m_buf + size, CLEAR "\r\n", 7);
size += 6;
# else
memcpy(m_buf + size, CLEAR "\n", 6);
size += 5;
# endif
}
char m_buf[Log::kMaxBufferSize]{};
std::mutex m_mutex;
std::vector<ILogBackend*> m_backends;
std::vector<ILogBackend*> backends;
};
#endif
bool Log::m_background = false;
bool Log::m_colors = true;
LogPrivate *Log::d = nullptr;
uint32_t Log::m_verbose = 0;
} /* namespace xmrig */
} // namespace xmrig
#ifndef XMRIG_FEATURE_EVENTS
void xmrig::Log::add(ILogBackend *backend)
{
assert(d != nullptr);
if (d) {
d->add(backend);
d->backends.push_back(backend);
}
}
@ -223,18 +263,25 @@ void xmrig::Log::init()
{
d = new LogPrivate();
}
#endif
void xmrig::Log::print(const char *fmt, ...)
{
# ifndef XMRIG_FEATURE_EVENTS
if (!d) {
return;
}
# endif
va_list args{};
va_start(args, fmt);
# ifdef XMRIG_FEATURE_EVENTS
log_print(NONE, fmt, args);
# else
d->print(NONE, fmt, args);
# endif
va_end(args);
}
@ -242,14 +289,33 @@ void xmrig::Log::print(const char *fmt, ...)
void xmrig::Log::print(Level level, const char *fmt, ...)
{
# ifndef XMRIG_FEATURE_EVENTS
if (!d) {
return;
}
# endif
va_list args{};
va_start(args, fmt);
# ifdef XMRIG_FEATURE_EVENTS
log_print(level, fmt, args);
# else
d->print(level, fmt, args);
# endif
va_end(args);
}
void xmrig::Log::setVerbose(uint32_t verbose)
{
static constexpr uint32_t kMaxVerbose =
# ifdef XMRIG_FEATURE_EVENTS
LogConfig::kMaxVerbose;
# else
5U;
# endif
m_verbose = std::min(verbose, kMaxVerbose);
}

View file

@ -1,7 +1,7 @@
/* XMRig
* Copyright (c) 2019 Spudz76 <https://github.com/Spudz76>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
* Copyright (c) 2018-2022 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2022 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -15,6 +15,13 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional permission under GNU GPL version 3 section 7
*
* If you modify this Program, or any covered work, by linking or combining
* it with OpenSSL (or a modified version of that library), containing parts
* covered by the terms of OpenSSL License and SSLeay License, the licensors
* of this Program grant you additional permission to convey the resulting work.
*/
#ifndef XMRIG_LOG_H
@ -44,16 +51,25 @@ public:
WARNING, // warning conditions
NOTICE, // normal but significant condition
INFO, // informational
V1, // Verbose
V2, // Verbose
V3, // Verbose
V4, // Verbose
V5, // Verbose
DEBUG, // debug-level messages
};
constexpr static size_t kMaxBufferSize = 16384;
# ifndef XMRIG_FEATURE_EVENTS
static void add(ILogBackend *backend);
static void destroy();
static void init();
# endif
static void print(const char *fmt, ...);
static void print(Level level, const char *fmt, ...);
static void setVerbose(uint32_t verbose);
static inline bool isBackground() { return m_background; }
static inline bool isColors() { return m_colors; }
@ -61,7 +77,6 @@ public:
static inline uint32_t verbose() { return m_verbose; }
static inline void setBackground(bool background) { m_background = background; }
static inline void setColors(bool colors) { m_colors = colors; }
static inline void setVerbose(uint32_t verbose) { m_verbose = verbose; }
private:
static bool m_background;
@ -143,12 +158,12 @@ private:
#define LOG_WARN(x, ...) xmrig::Log::print(xmrig::Log::WARNING, x, ##__VA_ARGS__)
#define LOG_NOTICE(x, ...) xmrig::Log::print(xmrig::Log::NOTICE, x, ##__VA_ARGS__)
#define LOG_INFO(x, ...) xmrig::Log::print(xmrig::Log::INFO, x, ##__VA_ARGS__)
#define LOG_VERBOSE(x, ...) if (xmrig::Log::verbose() > 0) { xmrig::Log::print(xmrig::Log::INFO, x, ##__VA_ARGS__); }
#define LOG_V1(x, ...) if (xmrig::Log::verbose() > 0) { xmrig::Log::print(xmrig::Log::INFO, x, ##__VA_ARGS__); }
#define LOG_V2(x, ...) if (xmrig::Log::verbose() > 1) { xmrig::Log::print(xmrig::Log::INFO, x, ##__VA_ARGS__); }
#define LOG_V3(x, ...) if (xmrig::Log::verbose() > 2) { xmrig::Log::print(xmrig::Log::INFO, x, ##__VA_ARGS__); }
#define LOG_V4(x, ...) if (xmrig::Log::verbose() > 3) { xmrig::Log::print(xmrig::Log::INFO, x, ##__VA_ARGS__); }
#define LOG_V5(x, ...) if (xmrig::Log::verbose() > 4) { xmrig::Log::print(xmrig::Log::INFO, x, ##__VA_ARGS__); }
#define LOG_VERBOSE(x, ...) if (xmrig::Log::verbose() > 0) { xmrig::Log::print(xmrig::Log::V1, x, ##__VA_ARGS__); }
#define LOG_V1(x, ...) if (xmrig::Log::verbose() > 0) { xmrig::Log::print(xmrig::Log::V1, x, ##__VA_ARGS__); }
#define LOG_V2(x, ...) if (xmrig::Log::verbose() > 1) { xmrig::Log::print(xmrig::Log::V2, x, ##__VA_ARGS__); }
#define LOG_V3(x, ...) if (xmrig::Log::verbose() > 2) { xmrig::Log::print(xmrig::Log::V3, x, ##__VA_ARGS__); }
#define LOG_V4(x, ...) if (xmrig::Log::verbose() > 3) { xmrig::Log::print(xmrig::Log::V4, x, ##__VA_ARGS__); }
#define LOG_V5(x, ...) if (xmrig::Log::verbose() > 4) { xmrig::Log::print(xmrig::Log::V5, x, ##__VA_ARGS__); }
#ifdef APP_DEBUG
# define LOG_DEBUG(x, ...) xmrig::Log::print(xmrig::Log::DEBUG, x, ##__VA_ARGS__)
@ -165,7 +180,7 @@ private:
#endif
} /* namespace xmrig */
} // namespace xmrig
#endif /* XMRIG_LOG_H */
#endif // XMRIG_LOG_H