diff --git a/index.html b/index.html
index 2c6d5613..934a6d3f 100644
--- a/index.html
+++ b/index.html
@@ -411,15 +411,24 @@
var data = table.row( $(this).parents('tr') ).data();
var clientId = data['client_status']['client_id'];
var clientIp = data['client_status']['external_ip'];
- var log = data['client_status']['log'];
- var htmlContent = "
" +
- ""+
- "" +
- "
";
+ $.ajax({
+ type: "GET",
+ url: "/admin/getClientLog?clientId=" + clientId,
+ dataType:"json",
+ success: function(jsonClientLog) {
+ var htmlContent = "" +
+ ""+
+ "" +
+ "
";
- $('#minerLog').find('.modal-body').html(htmlContent);
- $('#minerLog').modal('show');
+ $('#minerLog').find('.modal-body').html(htmlContent);
+ $('#minerLog').modal('show');
+ },
+ error: function (data) {
+ setError('Unable to fetch ' + clientId + ' log. - Please make sure it is enabled on the miner!');
+ }
+ });
});
$('#minerLogRefresh').click(function(event) {
@@ -429,9 +438,17 @@
var row = table.row(index);
var data = row.data();
- if (clientId === data.client_status.client_id) {
- $('#log').val(data.client_status.log);
- }
+ $.ajax({
+ type: "GET",
+ url: "/admin/getClientLog?clientId=" + clientId,
+ dataType:"json",
+ success: function(jsonClientLog) {
+ $('#log').val(JSON.stringify(jsonClientLog,undefined, 2));
+ },
+ error: function (data) {
+ setError('Unable to fetch ' + clientId + ' log. - Please make sure it is enabled on the miner!');
+ }
+ });
});
});
diff --git a/src/App.cpp b/src/App.cpp
index 04ad9dde..0b549eda 100644
--- a/src/App.cpp
+++ b/src/App.cpp
@@ -90,7 +90,8 @@ App::App(int argc, char **argv) :
}
if (m_options->ccUseRemoteLogging()) {
- Log::add(new RemoteLog());
+ // 20 lines per second should be enough
+ Log::add(new RemoteLog(static_cast(m_options->ccUpdateInterval() * 20)));
}
# ifdef HAVE_SYSLOG_H
diff --git a/src/Options.cpp b/src/Options.cpp
index 0fa73004..7392eb13 100644
--- a/src/Options.cpp
+++ b/src/Options.cpp
@@ -110,6 +110,7 @@ Options:\n"
--cc-use-tls enable tls encryption for CC communication\n\
--cc-cert-file=FILE when tls is turned on, use this to point to the right cert file (default: server.pem) \n\
--cc-key-file=FILE when tls is turned on, use this to point to the right key file (default: server.key) \n\
+ --client-log-lines-history=N maximum lines of log history kept per miner \n\
--cc-client-config-folder=FOLDER Folder contains the client config files\n\
--cc-custom-dashboard=FILE loads a custom dashboard and serve it to '/'\n"
# endif
@@ -182,6 +183,7 @@ static struct option const options[] = {
{ "cc-key-file", 1, nullptr, 4015 },
{ "cc-use-tls", 0, nullptr, 4016 },
{ "cc-use-remote-logging", 0, nullptr, 4017 },
+ { "cc-client-log-lines-history", 1, nullptr, 4018 },
{ "daemonized", 0, nullptr, 4011 },
{ "doublehash-thread-mask", 1, nullptr, 4013 },
{ "multihash-thread-mask", 1, nullptr, 4013 },
@@ -257,6 +259,7 @@ static struct option const cc_server_options[] = {
{ "cert-file", 1, nullptr, 4014 },
{ "key-file", 1, nullptr, 4015 },
{ "use-tls", 0, nullptr, 4016 },
+ { "client-log-lines-history", 1, nullptr, 4018 },
{ nullptr, 0, nullptr, 0 }
};
@@ -346,6 +349,7 @@ Options::Options(int argc, char **argv) :
m_threads(0),
m_ccUpdateInterval(10),
m_ccPort(0),
+ m_ccClientLogLinesHistory(100),
m_affinity(-1L),
m_multiHashThreadMask(-1L)
{
@@ -558,6 +562,8 @@ bool Options::parseArg(int key, const char *arg)
case 4006: /* --cc-port */
case 4012: /* --cc-update-interval-c */
return parseArg(key, strtol(arg, nullptr, 10));
+ case 4018: /* --cc-client-log-lines-history */
+ return parseArg(key, strtol(arg, nullptr, 25));
case 'B': /* --background */
case 'k': /* --keepalive */
@@ -756,6 +762,10 @@ bool Options::parseArg(int key, uint64_t arg)
}
break;
+ case 4018: /* --cc-client-log-lines-history */
+ m_ccClientLogLinesHistory = (int) arg;
+ break;
+
default:
break;
}
diff --git a/src/Options.h b/src/Options.h
index 911b508a..cc89e887 100644
--- a/src/Options.h
+++ b/src/Options.h
@@ -101,6 +101,7 @@ public:
inline size_t threads() const { return m_threads; }
inline int ccUpdateInterval() const { return m_ccUpdateInterval; }
inline int ccPort() const { return m_ccPort; }
+ inline size_t ccClientLogLinesHistory() const { return m_ccClientLogLinesHistory; }
inline int64_t affinity() const { return m_affinity; }
inline int64_t multiHashThreadMask() const { return m_multiHashThreadMask; }
inline void setColors(bool colors) { m_colors = colors; }
@@ -175,6 +176,7 @@ private:
size_t m_threads;
int m_ccUpdateInterval;
int m_ccPort;
+ size_t m_ccClientLogLinesHistory;
int64_t m_affinity;
int64_t m_multiHashThreadMask;
std::vector m_pools;
diff --git a/src/cc/ClientStatus.cpp b/src/cc/ClientStatus.cpp
index 1a040907..cddb8c89 100644
--- a/src/cc/ClientStatus.cpp
+++ b/src/cc/ClientStatus.cpp
@@ -150,6 +150,11 @@ void ClientStatus::setLog(const std::string& log)
m_log = log;
}
+void ClientStatus::clearLog()
+{
+ m_log.clear();
+}
+
bool ClientStatus::hasHugepages() const
{
return m_hasHugepages;
diff --git a/src/cc/ClientStatus.h b/src/cc/ClientStatus.h
index 66a9b6f2..e8204126 100644
--- a/src/cc/ClientStatus.h
+++ b/src/cc/ClientStatus.h
@@ -82,7 +82,8 @@ public:
void setVersion(const std::string& version);
std::string getLog() const;
- void setLog(const std::string& version);
+ void setLog(const std::string& log);
+ void clearLog();
bool hasHugepages() const;
void setHugepages(bool hasHugepages);
diff --git a/src/cc/Service.cpp b/src/cc/Service.cpp
index 72719e13..6c9e317b 100644
--- a/src/cc/Service.cpp
+++ b/src/cc/Service.cpp
@@ -40,7 +40,7 @@
uv_mutex_t Service::m_mutex;
std::map Service::m_clientCommand;
std::map Service::m_clientStatus;
-std::map> Service::m_remoteLog;
+std::map> Service::m_clientLog;
int Service::m_currentServerTime = 0;
@@ -57,7 +57,7 @@ void Service::release()
m_clientCommand.clear();
m_clientStatus.clear();
- m_remoteLog.clear();
+ m_clientLog.clear();
uv_mutex_unlock(&m_mutex);
}
@@ -81,7 +81,7 @@ unsigned Service::handleGET(const Options* options, const std::string& url, cons
} else if (url.rfind("/admin/getClientCommand", 0) == 0) {
resultCode = getClientCommand(clientId, resp);
} else if (url.rfind("/admin/getClientLog", 0) == 0) {
- //resultCode = getClientCommand(clientId, resp);
+ resultCode = getClientLog(clientId, resp);
}
}
else {
@@ -105,7 +105,7 @@ unsigned Service::handlePOST(const Options* options, const std::string& url, con
url.c_str(), clientIp.c_str(), clientId.c_str(), data.length());
if (url.rfind("/client/setClientStatus", 0) == 0) {
- resultCode = setClientStatus(clientIp, clientId, data, resp);
+ resultCode = setClientStatus(options, clientIp, clientId, data, resp);
} else if (url.rfind("/admin/setClientConfig", 0) == 0 || url.rfind("/client/setClientConfig", 0) == 0) {
resultCode = setClientConfig(options, clientId, data, resp);
} else if (url.rfind("/admin/setClientCommand", 0) == 0) {
@@ -221,7 +221,7 @@ unsigned Service::getClientStatusList(std::string& resp)
return MHD_HTTP_OK;
}
-unsigned Service::setClientStatus(const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp)
+unsigned Service::setClientStatus(const Options* options, const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp)
{
int resultCode = MHD_HTTP_BAD_REQUEST;
@@ -233,6 +233,10 @@ unsigned Service::setClientStatus(const std::string& clientIp, const std::string
clientStatus.parseFromJson(document);
clientStatus.setExternalIp(clientIp);
+ setClientLog(options->ccClientLogLinesHistory(), clientId, clientStatus.getLog());
+
+ clientStatus.clearLog();
+
m_clientStatus[clientId] = clientStatus;
resultCode = getClientCommand(clientId, resp);
@@ -271,40 +275,22 @@ unsigned Service::getClientCommand(const std::string& clientId, std::string& res
return MHD_HTTP_OK;
}
-unsigned Service::setClientCommand(const std::string& clientId, const std::string& data, std::string& resp)
-{
- ControlCommand controlCommand;
-
- rapidjson::Document document;
- if (!document.Parse(data.c_str()).HasParseError()) {
- controlCommand.parseFromJson(document);
-
- m_clientCommand[clientId] = controlCommand;
-
- return MHD_HTTP_OK;
- } else {
- return MHD_HTTP_BAD_REQUEST;
- }
-}
-
-unsigned Service::resetClientStatusList(const std::string& data, std::string& resp)
-{
- m_clientStatus.clear();
-
- return MHD_HTTP_OK;
-}
-
unsigned Service::getClientLog(const std::string& clientId, std::string& resp)
{
- if (m_remoteLog.find(clientId) != m_remoteLog.end()) {
-
+ if (m_clientLog.find(clientId) != m_clientLog.end()) {
rapidjson::Document respDocument;
respDocument.SetObject();
auto& allocator = respDocument.GetAllocator();
- rapidjson::Value controlCommand = m_clientCommand[clientId].toJson(allocator);
- respDocument.AddMember("client_log", controlCommand, allocator);
+ std::stringstream data;
+ for (auto& m_row : m_clientLog[clientId]) {
+ data << m_row.c_str() << std::endl;
+ }
+
+ LOG_INFO("LOG: %s", data.str().c_str());
+
+ respDocument.AddMember("client_log", rapidjson::StringRef(data.str().c_str()), allocator);
rapidjson::StringBuffer buffer(0, 4096);
rapidjson::Writer writer(buffer);
@@ -351,6 +337,49 @@ unsigned Service::getAdminPage(const Options* options, std::string& resp)
return MHD_HTTP_OK;
}
+unsigned Service::setClientCommand(const std::string& clientId, const std::string& data, std::string& resp)
+{
+ ControlCommand controlCommand;
+
+ rapidjson::Document document;
+ if (!document.Parse(data.c_str()).HasParseError()) {
+ controlCommand.parseFromJson(document);
+
+ m_clientCommand[clientId] = controlCommand;
+
+ return MHD_HTTP_OK;
+ } else {
+ return MHD_HTTP_BAD_REQUEST;
+ }
+}
+
+void Service::setClientLog(size_t maxRows, const std::string& clientId, const std::string& log)
+{
+ if (m_clientLog.find(clientId) == m_clientLog.end()) {
+ m_clientLog[clientId] = std::list();
+ }
+
+ auto* clientLog = &m_clientLog[clientId];
+ std::istringstream logStream(log);
+
+ std::string logLine;
+ while (std::getline(logStream, logLine))
+ {
+ if (clientLog->size() == maxRows) {
+ clientLog->pop_front();
+ }
+
+ clientLog->push_back(logLine);
+ }
+}
+
+unsigned Service::resetClientStatusList(const std::string& data, std::string& resp)
+{
+ m_clientStatus.clear();
+
+ return MHD_HTTP_OK;
+}
+
std::string Service::getClientConfigFileName(const Options* options, const std::string& clientId)
{
std::string clientConfigFileName;
diff --git a/src/cc/Service.h b/src/cc/Service.h
index 98d0ee03..e909debd 100644
--- a/src/cc/Service.h
+++ b/src/cc/Service.h
@@ -52,11 +52,13 @@ private:
static unsigned getClientStatusList(std::string& resp);
static unsigned getAdminPage(const Options* options, std::string& resp);
- static unsigned setClientStatus(const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp);
+ static unsigned setClientStatus(const Options* options, const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp);
static unsigned setClientCommand(const std::string& clientId, const std::string& data, std::string& resp);
static unsigned setClientConfig(const Options* options, const std::string &clientId, const std::string &data, std::string &resp);
static unsigned resetClientStatusList(const std::string& data, std::string& resp);
+ static void setClientLog(size_t maxRows, const std::string& clientId, const std::string& log);
+
static std::string getClientConfigFileName(const Options *options, const std::string &clientId);
private:
@@ -64,7 +66,7 @@ private:
static std::map m_clientStatus;
static std::map m_clientCommand;
- static std::map> m_remoteLog;
+ static std::map> m_clientLog;
static uv_mutex_t m_mutex;
diff --git a/src/config_cc.json b/src/config_cc.json
index 2b716a0d..ea4e492a 100644
--- a/src/config_cc.json
+++ b/src/config_cc.json
@@ -12,6 +12,7 @@
"user": "admin", // admin user for access CC Dashboard
"pass": "pass", // admin pass for access CC Dashboard
"client-config-folder" : null, // folder which contains the client-config files (null=current)
+ "client-log-lines-history" : 100, // maximum lines of log history kept per miner
"custom-dashboard" : "index.html" // dashboard html file
}
}
diff --git a/src/log/Log.cpp b/src/log/Log.cpp
index f37d4424..906ddf17 100644
--- a/src/log/Log.cpp
+++ b/src/log/Log.cpp
@@ -35,7 +35,6 @@
Log *Log::m_self = nullptr;
-
Log::Log()
{
uv_mutex_init(&m_mutex);
diff --git a/src/log/RemoteLog.cpp b/src/log/RemoteLog.cpp
index d0d93caa..f5552d09 100644
--- a/src/log/RemoteLog.cpp
+++ b/src/log/RemoteLog.cpp
@@ -22,8 +22,8 @@
RemoteLog* RemoteLog::m_self = nullptr;
-RemoteLog::RemoteLog()
- : m_maxRows(100)
+RemoteLog::RemoteLog(size_t maxRows)
+ : m_maxRows(maxRows)
{
uv_mutex_init(&m_mutex);
diff --git a/src/log/RemoteLog.h b/src/log/RemoteLog.h
index 07e8a768..973cc8f5 100644
--- a/src/log/RemoteLog.h
+++ b/src/log/RemoteLog.h
@@ -29,7 +29,7 @@
class RemoteLog : public ILogBackend
{
public:
- RemoteLog();
+ RemoteLog(size_t maxRows);
~RemoteLog();
void message(int level, const char* fmt, va_list args) override;