Skip to content

Commit

Permalink
Rework of miner_getstatDetail
Browse files Browse the repository at this point in the history
Reorganized the output from miner_getstatDetail API call.
Reduced verbosity and created groups and arrays
Added info about devices
  • Loading branch information
AndreaLanfranchi committed Dec 2, 2018
1 parent 70c7cdb commit ad55af9
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 161 deletions.
117 changes: 59 additions & 58 deletions docs/API_DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,73 +185,74 @@ and expect back a response like this:

```js
{
"id": 1,
"id": 0,
"jsonrpc": "2.0",
"result": {
"connection": { // Current active connection
"isconnected": true,
"switched": 0,
"uri": "stratum+tcp://<omitted-ethereum-address>.worker@eu1.ethermine.org:4444"
"connected": true,
"switches": 1,
"uri": "stratum1+tls12://0x4813aEEE0c30C584C559fa8Dc7424481E2e9Fc91.BG01R01@eu1.ethermine.org:5555"
},
"difficulty": 3999938964.0,
"epoch": 218,
"epoch_changes": 1, // Ethminer starts with epoch 0. First connection to pool increments this counter
"hashrate": 46709128, // Overall HashRate in H/s
"hostname": "<omitted-hostname>",
"runtime": 240, // Total running time in seconds
"shares": { // Summarized info about shares
"accepted": 5,
"acceptedstale": 1,
"invalid": 1,
"lastupdate": 58, // Latest update of any share info of is X seconds ago
"rejected": 0
},
"tstart": 63,
"tstop": 69,
"version": "ethminer-0.16.0.dev3-73+commit.f35c22ab",
"gpus": [
{"fan": 54, // Fan in %
"hashrate": 23604564, // HashRate of GPU in H/s
"index": 0,
"ispaused": false,
"nonce_start": 6636918940706763208,
"nonce_stop": 6636920040218390984,
"pause_reason": "", // Possible values: "", "temperature", "api", or "temperature,api"
"power": 0.0, // Powerdrain in W
"shares": { // Detailed info about shares from this GPU
"accepted": 3,
"acceptedstale": 0,
"invalid": 0,
"lastupdate": 58, // Share info from this GPU updated X seconds ago
"rejected": 0
},
"temp": 53 // Temperature in °C
"devices": [ // Array subscribed of devices
{
"_index": 0, // Miner ordinal
"_mode": "CUDA", // Miner mode : "OpenCL" / "CUDA"
"hardware": { // Device hardware info
"name": "GeForce GTX 1050 Ti 3.95 GB", // Name
"pci": "01:00.0", // Pci Id
"sensors": [ // An array made of ...
47, // + Detected temp
70, // + Fan percent
0 // + Power drain in watts
],
"type": "GPU" // Device Type : "CPU" / "GPU" / "ACCELERATOR"
},
"mining": { // Mining info
"hashrate": "0x0000000000e3fcbb", // Current hashrate in hashes per second
"pause_reason": null, // If the device is paused this contains the reason
"paused": false, // Wheter or not the device is paused
"segment": [ // The search segment of the device
"0xbcf0a663bfe75dab", // + Lower bound
"0xbcf0a664bfe75dab" // + Upper bound
],
"shares": [ // Shares / Solutions stats
1, // + Found shares
0, // + Rejected (by pool) shares
0, // + Failed shares (always 0 if --no-eval is set)
15 // + Time in seconds since last found share
]
}
},
{"fan": 53,
"hashrate": 23104564,
"index": 1,
"ispaused": false,
"nonce_start": 6636920040218391000,
"nonce_stop": 6636921139730018000,
"pause_reason": "",
"power": 0.0,
"shares": {
"accepted": 2,
"acceptedstale": 1,
"invalid": 1,
"lastupdate": 134,
"rejected": 0
},
"temp": 56
}
]
{ ... } // Another device
{ ... } // And another ...
],
"host": {
"name": "miner01", // Host name of the computer running ethminer
"runtime": 121, // Duration time (in seconds)
"version": "ethminer-0.18.0-alpha.1+commit.70c7cdbe.dirty"
},
"mining": { // Mining info for the whole instance
"difficulty": 3999938964, // Actual difficulty in hashes
"epoch": 227, // Current epoch
"epoch_changes": 1, // How many epoch changes occurred during the run
"hashrate": "0x00000000054a89c8", // Overall hashrate (sum of hashrate of all devices)
"shares": [ // Shares / Solutions stats
2, // + Found shares
0, // + Rejected (by pool) shares
0, // + Failed shares (always 0 if --no-eval is set)
15 // + Time in seconds since last found share
]
},
"monitors": { // A nullable object which may contain some triggers
"temperatures": [ // Monitor temperature
60, // + Resume mining if device temp is <= this threshold
75 // + Suspend mining if device temp is >= this threshold
]
}
}
}
```

If values not set (eg --tstart) or the underlaying function returns an error expect `null` as returned value!


### miner_getstat1

With this method you expect back a collection of statistical data. To issue a request:
Expand Down
200 changes: 103 additions & 97 deletions libapicore/ApiServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -924,62 +924,71 @@ Json::Value ApiConnection::getMinerStatHR()
}


Json::Value ApiConnection::getMinerStatDetailPerMiner(const WorkingProgress& p,
const SolutionStats& s, size_t index, const std::chrono::steady_clock::time_point& now)
Json::Value ApiConnection::getMinerStatDetailPerMiner(const WorkingProgress& _p,
const SolutionStats& _s, std::shared_ptr<Miner> _miner)
{
Json::Value jRes;
auto const& miner = Farm::f().getMiner(index);

jRes["index"] = (unsigned)index;

/* Hash & Share infos */
if (index < p.minersHashRates.size())
jRes["hashrate"] = (uint64_t)p.minersHashRates[index];
else
jRes["hashrate"] = Json::Value::null;
unsigned _index = _miner->Index();
std::chrono::steady_clock::time_point _now = std::chrono::steady_clock::now();

Json::Value jshares;
jshares["accepted"] = s.getAccepts(index);
jshares["rejected"] = s.getRejects(index);
jshares["invalid"] = s.getFailures(index);

auto solution_lastupdated =
std::chrono::duration_cast<std::chrono::seconds>(now - s.getLastUpdated(index));
jshares["lastupdate"] = uint64_t(solution_lastupdated.count()); // last update of this gpu stat was x seconds ago
jRes["shares"] = jshares;


/* Hardware */
if (index < p.minerMonitors.size())
{
jRes["temp"] = p.minerMonitors[index].tempC;
jRes["fan"] = p.minerMonitors[index].fanP;
jRes["power"] = p.minerMonitors[index].powerW;
}
else
Json::Value jRes;
DeviceDescriptorType minerDescriptor = _miner->getDescriptor();

jRes["_index"] = _index;
jRes["_mode"] =
(minerDescriptor.SubscriptionType == DeviceSubscriptionTypeEnum::Cuda ? "CUDA" : "OpenCL");

/* Hardware Info */
Json::Value hwinfo;
hwinfo["pci"] = minerDescriptor.UniqueId;
hwinfo["type"] = (minerDescriptor.Type == DeviceTypeEnum::Gpu ? "GPU"
: (minerDescriptor.Type == DeviceTypeEnum::Accelerator ? "ACCELERATOR" : "CPU" ));
ostringstream ss;
ss << (minerDescriptor.clDetected ? minerDescriptor.clName : minerDescriptor.cuName) << " "
<< FormattedMemSize(minerDescriptor.TotalMemory);
hwinfo["name"] = ss.str();

/* Hardware Sensors*/
Json::Value sensors = Json::Value(Json::arrayValue);
if (_index < _p.minerMonitors.size())
{
jRes["temp"] = jRes["fan"] = jRes["power"] = Json::Value::null;
sensors.append(_p.minerMonitors[_index].tempC);
sensors.append(_p.minerMonitors[_index].fanP);
sensors.append(_p.minerMonitors[_index].powerW);
}
hwinfo["sensors"] = sensors;

/* Mining Info */
Json::Value mininginfo;
Json::Value jshares = Json::Value(Json::arrayValue);
Json::Value jsegment = Json::Value(Json::arrayValue);
jshares.append(_s.getAccepts(_index));
jshares.append(_s.getRejects(_index));
jshares.append(_s.getFailures(_index));

auto solution_lastupdated =
std::chrono::duration_cast<std::chrono::seconds>(_now - _s.getLastUpdated(_index));
jshares.append(uint64_t(solution_lastupdated.count())); // interval in seconds from last found
// share

// TODO: PCI ID, Name, ... (some more infos - see listDevices())

/* Pause infos */
if (miner && index < p.miningIsPaused.size())
{
bool paused = miner->paused();
jRes["ispaused"] = paused;
jRes["pause_reason"] = (paused ? miner->pausedString() : Json::Value::null);
}
else
{
jRes["ispaused"] = jRes["pause_reason"] = Json::Value::null;
}
mininginfo["shares"] = jshares;
mininginfo["paused"] = _miner->paused();
mininginfo["pause_reason"] = _miner->paused() ? _miner->pausedString() : Json::Value::null;

/* Nonce infos */
auto segment_width = Farm::f().get_segment_width();
uint64_t gpustartnonce = Farm::f().get_nonce_scrambler() + ((uint64_t)index << segment_width);
jRes["nonce_start"] = gpustartnonce;
jRes["nonce_stop"] = uint64_t(gpustartnonce + (1LL << segment_width));
uint64_t gpustartnonce = Farm::f().get_nonce_scrambler() + ((uint64_t)_index << segment_width);
jsegment.append(toHex(uint64_t(gpustartnonce), HexPrefix::Add));
jsegment.append(toHex(uint64_t(gpustartnonce + (1LL << segment_width)), HexPrefix::Add));
mininginfo["segment"] = jsegment;

/* Hash & Share infos */
if (_index < _p.minersHashRates.size())
mininginfo["hashrate"] = toHex((uint32_t)_p.minersHashRates[_index], HexPrefix::Add);
else
mininginfo["hashrate"] = Json::Value::null;

jRes["hardware"] = hwinfo;
jRes["mining"] = mininginfo;

return jRes;
}
Expand All @@ -1004,73 +1013,70 @@ Json::Value ApiConnection::getMinerStatDetail()
WorkingProgress p = Farm::f().miningProgress();

// ostringstream version;
Json::Value gpus;
Json::Value devices = Json::Value(Json::arrayValue);
Json::Value jRes;

jRes["version"] = ethminer_get_buildinfo()->project_name_with_version; // miner version.
jRes["runtime"] = uint64_t(runningTime.count()); // running time, in seconds.
/* Host Info */
Json::Value hostinfo;
hostinfo["version"] = ethminer_get_buildinfo()->project_name_with_version; // miner version.
hostinfo["runtime"] = uint64_t(runningTime.count()); // running time, in seconds.

{
// Even the client should know which host was queried
char hostName[HOST_NAME_MAX + 1];
if (!gethostname(hostName, HOST_NAME_MAX + 1))
jRes["hostname"] = hostName;
hostinfo["name"] = hostName;
else
jRes["hostname"] = Json::Value::null;
hostinfo["name"] = Json::Value::null;
}

/* connection info */

/* Connection info */
Json::Value connectioninfo;
auto connection = PoolManager::p().getActiveConnectionCopy();
Json::Value jconnection;
jconnection["uri"] = connection.str();
// jconnection["endpoint"] = PoolManager::p().getClient()->ActiveEndPoint();
jconnection["isconnected"] = PoolManager::p().isConnected();
jconnection["switched"] = PoolManager::p().getConnectionSwitches();
jRes["connection"] = jconnection;

/* Pool info */
jRes["difficulty"] = PoolManager::p().getCurrentDifficulty();
jRes["epoch"] = PoolManager::p().getCurrentEpoch();
jRes["epoch_changes"] = PoolManager::p().getEpochChanges();

/* basic setup */
connectioninfo["uri"] = connection.str();
connectioninfo["connected"] = PoolManager::p().isConnected();
connectioninfo["switches"] = PoolManager::p().getConnectionSwitches();

/* Mining Info */
Json::Value mininginfo;
Json::Value sharesinfo = Json::Value(Json::arrayValue);

mininginfo["hashrate"] = toHex(uint32_t(p.hashRate), HexPrefix::Add);
mininginfo["epoch"] = PoolManager::p().getCurrentEpoch();
mininginfo["epoch_changes"] = PoolManager::p().getEpochChanges();
mininginfo["difficulty"] = PoolManager::p().getCurrentDifficulty();

sharesinfo.append(s.getAccepts());
sharesinfo.append(s.getRejects());
sharesinfo.append(s.getFailures());
auto solution_lastupdated =
std::chrono::duration_cast<std::chrono::seconds>(now - s.getLastUpdated());
sharesinfo.append(uint64_t(solution_lastupdated.count())); // interval in seconds from last
// found share
mininginfo["shares"] = sharesinfo;

/* Monitors Info */
Json::Value monitorinfo;
auto tstop = Farm::f().get_tstop();
if (tstop)
{
jRes["tstart"] = Farm::f().get_tstart();
jRes["tstop"] = tstop;
}
else
{
jRes["tstart"] = jRes["tstop"] = Json::Value::null;
Json::Value tempsinfo = Json::Value(Json::arrayValue);
tempsinfo.append(Farm::f().get_tstart());
tempsinfo.append(tstop);
monitorinfo["temperatures"] = tempsinfo;
}

/* gpu related info */
if (Farm::f().getMiners().size())
{
for (size_t i = 0; i < Farm::f().getMiners().size(); i++)
{
jRes["gpus"].append(getMinerStatDetailPerMiner(p, s, i, now));
}
}
else
{
jRes["gpus"] = Json::Value::null;
}
/* Devices related info */
for (shared_ptr<Miner> miner : Farm::f().getMiners())
devices.append(getMinerStatDetailPerMiner(p, s, miner));

// total ETH hashrate
jRes["hashrate"] = uint64_t(p.hashRate);
jRes["devices"] = devices;

// share information
Json::Value jshares;
jshares["accepted"] = s.getAccepts();
jshares["rejected"] = s.getRejects();
jshares["invalid"] = s.getFailures();
auto solution_lastupdated =
std::chrono::duration_cast<std::chrono::seconds>(now - s.getLastUpdated());
jshares["lastupdate"] =
uint64_t(solution_lastupdated.count()); // last update of this gpu stat was x seconds ago
jRes["shares"] = jshares;
jRes["monitors"] = monitorinfo;
jRes["connection"] = connectioninfo;
jRes["host"] = hostinfo;
jRes["mining"] = mininginfo;

return jRes;
}
4 changes: 2 additions & 2 deletions libapicore/ApiServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class ApiConnection
void onSendSocketDataCompleted(const boost::system::error_code& ec);

Json::Value getMinerStatDetail();
Json::Value getMinerStatDetailPerMiner(const WorkingProgress& p, const SolutionStats& s,
size_t index, const std::chrono::steady_clock::time_point& now);
Json::Value getMinerStatDetailPerMiner(
const WorkingProgress& _p, const SolutionStats& _s, std::shared_ptr<Miner> _miner);

Disconnected m_onDisconnected;

Expand Down
7 changes: 7 additions & 0 deletions libdevcore/CommonData.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,13 @@ inline std::string toHex(uint64_t _n, HexPrefix _prefix = HexPrefix::DontAdd)
return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
}

inline std::string toHex(uint32_t _n, HexPrefix _prefix = HexPrefix::DontAdd)
{
std::ostringstream ret;
ret << std::hex << std::setfill('0') << std::setw(sizeof(_n) * 2) << _n;
return (_prefix == HexPrefix::Add) ? "0x" + ret.str() : ret.str();
}

// Algorithms for string and string-like collections.

/// Escapes a string into the C-string representation.
Expand Down
Loading

0 comments on commit ad55af9

Please sign in to comment.