diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f2c4372b..2c9d95f8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,10 @@ set(HEADERS src/Cpu.h src/interfaces/IClientListener.h src/interfaces/IJobResultListener.h + src/interfaces/ILogBackend.h src/interfaces/IWorker.h + src/log/ConsoleLog.h + src/log/FileLog.h src/log/Log.h src/Mem.h src/net/Client.h @@ -45,6 +48,8 @@ set(HEADERS_CRYPTO set(SOURCES src/App.cpp + src/log/ConsoleLog.cpp + src/log/FileLog.cpp src/log/Log.cpp src/Mem.cpp src/net/Client.cpp diff --git a/src/App.cpp b/src/App.cpp index 3586889b6..934b98b38 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -27,9 +27,11 @@ #include "App.h" -#include "log/Log.h" #include "Cpu.h" #include "crypto/CryptoNight.h" +#include "log/ConsoleLog.h" +#include "log/FileLog.h" +#include "log/Log.h" #include "Mem.h" #include "net/Network.h" #include "Options.h" @@ -51,7 +53,15 @@ App::App(int argc, char **argv) : Cpu::init(); m_options = Options::parse(argc, argv); - Log::init(m_options->colors(), m_options->background()); + Log::init(); + + if (!m_options->background()) { + Log::add(new ConsoleLog(m_options->colors())); + } + + if (m_options->logFile()) { + Log::add(new FileLog(m_options->logFile())); + } m_network = new Network(m_options); diff --git a/src/Options.cpp b/src/Options.cpp index 6fccbe4c5..5929d0627 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -68,6 +68,12 @@ Options:\n\ --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)\n\ -B, --background run the miner in the background\n\ -c, --config=FILE load a JSON-format configuration file\n\ + -l, --log-file=FILE log all output to a file\n" +# ifdef HAVE_SYSLOG_H +"\ + -S, --syslog use system log for output messages\n" +# endif +"\ --max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\ --safe safe adjust threads and av settings for current CPU\n\ --nicehash enable nicehash support\n\ @@ -77,7 +83,7 @@ Options:\n\ "; -static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vb:"; +static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vb:l:S"; static struct option const options[] = { @@ -90,6 +96,7 @@ static struct option const options[] = { { "donate-level", 1, nullptr, 1003 }, { "help", 0, nullptr, 'h' }, { "keepalive", 0, nullptr ,'k' }, + { "log-file", 1, nullptr, 'l' }, { "max-cpu-usage", 1, nullptr, 1004 }, { "nicehash", 0, nullptr, 1006 }, { "no-color", 0, nullptr, 1002 }, @@ -98,6 +105,7 @@ static struct option const options[] = { { "retries", 1, nullptr, 'r' }, { "retry-pause", 1, nullptr, 'R' }, { "safe", 0, nullptr, 1005 }, + { "syslog", 0, nullptr, 'S' }, { "threads", 1, nullptr, 't' }, { "url", 1, nullptr, 'o' }, { "user", 1, nullptr, 'u' }, @@ -139,6 +147,8 @@ Options::Options(int argc, char **argv) : m_nicehash(false), m_ready(false), m_safe(false), + m_syslog(false), + m_logFile(nullptr), m_pass(nullptr), m_user(nullptr), m_algo(0), @@ -263,6 +273,12 @@ bool Options::parseArg(int key, char *arg) m_pass = strdup(arg); break; + case 'l': /* --log-file */ + free(m_logFile); + m_logFile = strdup(arg); + m_colors = false; + break; + case 'r': /* --retries */ v = strtol(arg, nullptr, 10); if (v < 1 || v > 1000) { @@ -324,6 +340,11 @@ bool Options::parseArg(int key, char *arg) m_colors = false; break; + case 'S': /* --syslog */ + m_syslog = true; + m_colors = false; + break; + case 'v': /* --av */ v = strtol(arg, nullptr, 10); if (v < 0 || v > 1000) { diff --git a/src/Options.h b/src/Options.h index c100f6d69..907819b7f 100644 --- a/src/Options.h +++ b/src/Options.h @@ -57,6 +57,8 @@ public: inline bool isReady() const { return m_ready; } inline bool keepAlive() const { return m_keepAlive; } inline bool nicehash() const { return m_nicehash; } + inline bool syslog() const { return m_syslog; } + inline const char *logFile() const { return m_logFile; } inline const char *pass() const { return m_pass; } inline const char *user() const { return m_user; } inline const Url *backupUrl() const { return m_backupUrl; } @@ -98,6 +100,8 @@ private: bool m_nicehash; bool m_ready; bool m_safe; + bool m_syslog; + char *m_logFile; char *m_pass; char *m_user; int m_algo; diff --git a/src/interfaces/ILogBackend.h b/src/interfaces/ILogBackend.h new file mode 100644 index 000000000..458b504c4 --- /dev/null +++ b/src/interfaces/ILogBackend.h @@ -0,0 +1,41 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __ILOGBACKEND_H__ +#define __ILOGBACKEND_H__ + + +#include + + +class ILogBackend +{ +public: + virtual ~ILogBackend() {} + + virtual void message(int level, const char* fmt, va_list args) = 0; + virtual void text(const char* fmt, va_list args) = 0; +}; + + +#endif // __ILOGBACKEND_H__ diff --git a/src/log/ConsoleLog.cpp b/src/log/ConsoleLog.cpp new file mode 100644 index 000000000..d9e86318d --- /dev/null +++ b/src/log/ConsoleLog.cpp @@ -0,0 +1,112 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include +#include +#include +#include + + +#ifdef WIN32 +# include +# include +# include "3rdparty/winansi.h" +#endif + +#include "log/ConsoleLog.h" +#include "log/Log.h" + + +ConsoleLog::ConsoleLog(bool colors) : + m_colors(colors) +{ +} + + +void ConsoleLog::message(int level, const char* fmt, va_list args) +{ + time_t now = time(nullptr); + tm stime; + +# ifdef _WIN32 + localtime_s(&stime, &now); +# else + localtime_r(&now, &stime); +# endif + + const char* color = nullptr; + if (m_colors) { + switch (level) { + case Log::ERR: + color = Log::kCL_RED; + break; + + case Log::WARNING: + color = Log::kCL_YELLOW; + break; + + case Log::NOTICE: + color = Log::kCL_WHITE; + break; + + case Log::DEBUG: + color = Log::kCL_GRAY; + break; + + default: + color = ""; + break; + } + } + + const size_t len = 64 + strlen(fmt) + 2; + char *buf = static_cast(alloca(len)); + + sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n", + stime.tm_year + 1900, + stime.tm_mon + 1, + stime.tm_mday, + stime.tm_hour, + stime.tm_min, + stime.tm_sec, + m_colors ? color : "", + fmt, + m_colors ? Log::kCL_N : "" + ); + + vfprintf(stdout, buf, args); + fflush(stdout); +} + + +void ConsoleLog::text(const char* fmt, va_list args) +{ + const int len = 64 + strlen(fmt) + 2; + char *buf = static_cast(alloca(len)); + + sprintf(buf, "%s%s\n", fmt, m_colors ? Log::kCL_N : ""); + + vfprintf(stdout, buf, args); + fflush(stdout); +} diff --git a/src/log/ConsoleLog.h b/src/log/ConsoleLog.h new file mode 100644 index 000000000..9b6777a59 --- /dev/null +++ b/src/log/ConsoleLog.h @@ -0,0 +1,43 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __CONSOLELOG_H__ +#define __CONSOLELOG_H__ + + +#include "interfaces/ILogBackend.h" + + +class ConsoleLog : public ILogBackend +{ +public: + ConsoleLog(bool colors); + + void message(int level, const char* fmt, va_list args) override; + void text(const char* fmt, va_list args) override; + +private: + bool m_colors; +}; + +#endif /* __CONSOLELOG_H__ */ diff --git a/src/log/FileLog.cpp b/src/log/FileLog.cpp new file mode 100644 index 000000000..b08cd2038 --- /dev/null +++ b/src/log/FileLog.cpp @@ -0,0 +1,103 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include +#include +#include +#include + + +#ifdef WIN32 +# include +# include +# include "3rdparty/winansi.h" +#endif + + +#include "log/FileLog.h" + + +FileLog::FileLog(const char *fileName) +{ + uv_fs_t req; + m_file = uv_fs_open(uv_default_loop(), &req, fileName, O_CREAT | O_APPEND, 0644, nullptr); + uv_fs_req_cleanup(&req); +} + + +void FileLog::message(int level, const char* fmt, va_list args) +{ + if (m_file < 0) { + return; + } + + time_t now = time(nullptr); + tm stime; + +# ifdef _WIN32 + localtime_s(&stime, &now); +# else + localtime_r(&now, &stime); +# endif + + char *buf = static_cast(malloc(512)); + int size = snprintf(buf, 23, "[%d-%02d-%02d %02d:%02d:%02d] ", + stime.tm_year + 1900, + stime.tm_mon + 1, + stime.tm_mday, + stime.tm_hour, + stime.tm_min, + stime.tm_sec); + + size = vsnprintf(buf + size, 512 - size - 1, fmt, args) + size; + buf[size] = '\n'; + + write(buf, size + 1); +} + + +void FileLog::text(const char* fmt, va_list args) +{ + message(0, fmt, args); +} + + + +void FileLog::onWrite(uv_fs_t *req) +{ + free(req->data); + + uv_fs_req_cleanup(req); + free(req); +} + + +void FileLog::write(char *data, size_t size) +{ + uv_buf_t buf = uv_buf_init(data, size); + uv_fs_t *req = static_cast(malloc(sizeof(uv_fs_t))); + req->data = buf.base; + + uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, 0, FileLog::onWrite); +} diff --git a/src/log/FileLog.h b/src/log/FileLog.h new file mode 100644 index 000000000..2b3ca5d4b --- /dev/null +++ b/src/log/FileLog.h @@ -0,0 +1,50 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __FILELOG_H__ +#define __FILELOG_H__ + + +#include + + +#include "interfaces/ILogBackend.h" + + +class FileLog : public ILogBackend +{ +public: + FileLog(const char *fileName); + + void message(int level, const char* fmt, va_list args) override; + void text(const char* fmt, va_list args) override; + +private: + static void onWrite(uv_fs_t *req); + + void write(char *data, size_t size); + + int m_file; +}; + +#endif /* __FILELOG_H__ */ diff --git a/src/log/Log.cpp b/src/log/Log.cpp index d4037f705..6d509ae71 100644 --- a/src/log/Log.cpp +++ b/src/log/Log.cpp @@ -34,109 +34,42 @@ # include "3rdparty/winansi.h" #endif +#include "interfaces/ILogBackend.h" #include "log/Log.h" Log *Log::m_self = nullptr; -void Log::init(bool colors, bool background) -{ - if (!m_self) { - m_self = new Log(colors, background); - } -} - - void Log::message(Log::Level level, const char* fmt, ...) { - time_t now = time(nullptr); - tm stime; + va_list args; + va_start(args, fmt); -# ifdef _WIN32 - localtime_s(&stime, &now); -# else - localtime_r(&now, &stime); -# endif - - va_list ap; - va_start(ap, fmt); - - const char* color = nullptr; - if (m_colors) { - switch (level) { - case ERR: - color = kCL_RED; - break; - - case WARNING: - color = kCL_YELLOW; - break; - - case NOTICE: - color = kCL_WHITE; - break; - - case DEBUG: - color = kCL_GRAY; - break; - - default: - color = ""; - break; - } + for (ILogBackend *backend : m_backends) { + backend->message(level, fmt, args); } - const size_t len = 64 + strlen(fmt) + 2; - char *buf = static_cast(alloca(len)); - - sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n", - stime.tm_year + 1900, - stime.tm_mon + 1, - stime.tm_mday, - stime.tm_hour, - stime.tm_min, - stime.tm_sec, - m_colors ? color : "", - fmt, - m_colors ? kCL_N : "" - ); - - uv_mutex_lock(&m_mutex); - - vfprintf(stdout, buf, ap); - fflush(stdout); - - uv_mutex_unlock(&m_mutex); - - va_end(ap); + va_end(args); } void Log::text(const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); + va_list args; + va_start(args, fmt); - const int len = 64 + strlen(fmt) + 2; - char *buf = static_cast(alloca(len)); + for (ILogBackend *backend : m_backends) { + backend->text(fmt, args); + } - sprintf(buf, "%s%s\n", fmt, m_colors ? kCL_N : ""); - - uv_mutex_lock(&m_mutex); - - vfprintf(stdout, buf, ap); - fflush(stdout); - - uv_mutex_unlock(&m_mutex); - - va_end(ap); + va_end(args); } -Log::Log(bool colors, bool background) : - m_background(background), - m_colors(colors) +Log::~Log() { - uv_mutex_init(&m_mutex); + for (auto backend : m_backends) { + delete backend; + } } diff --git a/src/log/Log.h b/src/log/Log.h index 7e1d0b044..16e94e0b9 100644 --- a/src/log/Log.h +++ b/src/log/Log.h @@ -26,6 +26,10 @@ #include +#include + + +class ILogBackend; class Log @@ -50,19 +54,19 @@ public: constexpr static const char* kCL_GRAY = "\x1B[90m"; # endif - static inline Log* i() { return m_self; } - static void init(bool colors, bool background); + static inline Log* i() { return m_self; } + static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); } + static inline void init() { if (!m_self) { m_self = new Log();} } void message(Level level, const char* fmt, ...); void text(const char* fmt, ...); private: - Log(bool colors, bool background); + inline Log() {} + ~Log(); - bool m_background; - bool m_colors; static Log *m_self; - uv_mutex_t m_mutex; + std::vector m_backends; }; diff --git a/src/log/SysLog.cpp b/src/log/SysLog.cpp new file mode 100644 index 000000000..88d2e55a3 --- /dev/null +++ b/src/log/SysLog.cpp @@ -0,0 +1,40 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "log/SysLog.h" + + +SysLog::SysLog() +{ +} + + +void SysLog::message(int level, const char* fmt, va_list args) +{ +} + + +void SysLog::text(const char* fmt, va_list args) +{ +} diff --git a/src/log/SysLog.h b/src/log/SysLog.h new file mode 100644 index 000000000..5a27fe74b --- /dev/null +++ b/src/log/SysLog.h @@ -0,0 +1,40 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2016-2017 XMRig + * + * + * 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef __SYSLOG_BACKEND_H__ +#define __SYSLOG_BACKEND_H__ + + +#include "interfaces/ILogBackend.h" + + +class SysLog : public ILogBackend +{ +public: + SysLog(); + + void message(int level, const char* fmt, va_list args) override; + void text(const char* fmt, va_list args) override; +}; + +#endif /* __SYSLOG_BACKEND_H__ */