This commit is contained in:
BenDr0id 2018-07-27 17:18:57 +02:00
parent 527b557f9e
commit ed80e8a436
12 changed files with 117 additions and 50 deletions

View file

@ -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'];
$.ajax({
type: "GET",
url: "/admin/getClientLog?clientId=" + clientId,
dataType:"json",
success: function(jsonClientLog) {
var htmlContent = "<div class='form-group' id='viewer' data-value='" + clientId + "'>" +
"<label for='config'>Log of: " + clientId + " (" + clientIp + ")</label>"+
"<textarea class='form-control' rows='20' id='log'>" + log + "</textarea>" +
"<textarea class='form-control' rows='20' id='log'>" + JSON.stringify(jsonClientLog,undefined, 2) + "</textarea>" +
"</div>";
$('#minerLog').find('.modal-body').html(htmlContent);
$('#minerLog').modal('show');
},
error: function (data) {
setError('<strong>Unable to fetch ' + clientId + ' log.</strong> - Please make sure it is enabled on the miner!');
}
});
});
$('#minerLogRefresh').click(function(event) {
@ -429,11 +438,19 @@
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('<strong>Unable to fetch ' + clientId + ' log.</strong> - Please make sure it is enabled on the miner!');
}
});
});
});
$('#multiMinerEditorReplace').click(function(event) {
table.rows({ selected: true }).eq(0).each(function (index) {

View file

@ -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<size_t>(m_options->ccUpdateInterval() * 20)));
}
# ifdef HAVE_SYSLOG_H

View file

@ -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;
}

View file

@ -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<Url*> m_pools;

View file

@ -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;

View file

@ -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);

View file

@ -40,7 +40,7 @@
uv_mutex_t Service::m_mutex;
std::map<std::string, ControlCommand> Service::m_clientCommand;
std::map<std::string, ClientStatus> Service::m_clientStatus;
std::map<std::string, std::list<std::string>> Service::m_remoteLog;
std::map<std::string, std::list<std::string>> 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<rapidjson::StringBuffer> 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<std::string>();
}
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;

View file

@ -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<std::string, ClientStatus> m_clientStatus;
static std::map<std::string, ControlCommand> m_clientCommand;
static std::map<std::string, std::list<std::string>> m_remoteLog;
static std::map<std::string, std::list<std::string>> m_clientLog;
static uv_mutex_t m_mutex;

View file

@ -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
}
}

View file

@ -35,7 +35,6 @@
Log *Log::m_self = nullptr;
Log::Log()
{
uv_mutex_init(&m_mutex);

View file

@ -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);

View file

@ -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;