[UPDATE] Overhauled graphing stats

* [REMOVED] Pool/Combined hashrate graph until we have a proper SQL to
  generate this data. Volunteers?
* [ADDED] Worker and share rate statistics over time
* [ADDED] Admin setting to change graphing days (default: 1 day)
* [ADDED] Purge entries older than admin setting
* [REMOVED] Template files that aren't used anymore
This commit is contained in:
Sebastian Grewe 2014-07-17 08:13:31 +02:00
parent 226d2c8b54
commit 2c773fca42
8 changed files with 96 additions and 112 deletions

View File

@ -77,7 +77,7 @@ $log->logInfo(sprintf($strLogMask, 'purgeArchive', $affected, number_format(micr
$start = microtime(true); $start = microtime(true);
$status = 'OK'; $status = 'OK';
$message = ''; $message = '';
$affected = $statistics->purgeUserStats(); $affected = $statistics->purgeUserStats($setting->getValue('statistics_graphing_days', 1));
if ($affected === false) { if ($affected === false) {
$message = 'Failed to delete entries: ' . $statistics->getCronError(); $message = 'Failed to delete entries: ' . $statistics->getCronError();
$status = 'ERROR'; $status = 'ERROR';

View File

@ -698,19 +698,21 @@ class Statistics extends Base {
* @param $account_id int account id * @param $account_id int account id
* @return data array NOT FINISHED YET * @return data array NOT FINISHED YET
**/ **/
public function getHashrateByAccount($account_id, $format='array') { public function getHourlyMiningStatsByAccount($account_id, $format='array', $days = 1) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
timestamp, timestamp,
FROM_UNIXTIME(timestamp, '%Y-%m-%d %H:%i') AS time, FROM_UNIXTIME(timestamp, '%Y-%m-%d %H:%i') AS time,
AVG(hashrate) AS hashrate AVG(hashrate) AS hashrate,
AVG(workers) AS workers,
AVG(sharerate) AS sharerate
FROM " . $this->getUserStatsTableName() . " FROM " . $this->getUserStatsTableName() . "
WHERE FROM_UNIXTIME(timestamp) >= DATE_SUB(NOW(), INTERVAL 24 HOUR) WHERE FROM_UNIXTIME(timestamp) >= DATE_SUB(NOW(), INTERVAL $days DAY)
AND account_id = ? AND account_id = ?
GROUP BY HOUR(FROM_UNIXTIME(timestamp))"); GROUP BY DAY(FROM_UNIXTIME(timestamp)), HOUR(FROM_UNIXTIME(timestamp))");
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $account_id ) && $stmt->execute() && $result = $stmt->get_result()) { if ($this->checkStmt($stmt) && $stmt->bind_param('i', $account_id) && $stmt->execute() && $result = $stmt->get_result()) {
$aData = $result->fetch_all(MYSQLI_ASSOC); $aData = $result->fetch_all(MYSQLI_ASSOC);
if ($format == 'json') $aData = json_encode($aData); if ($format == 'json') $aData = json_encode($aData);
return $this->memcache->setCache(__FUNCTION__ . $account_id . $format, $aData); return $this->memcache->setCache(__FUNCTION__ . $account_id . $format, $aData);
@ -718,32 +720,6 @@ class Statistics extends Base {
return $this->sqlError(); return $this->sqlError();
} }
/**
* get Hourly hashrate for the pool
* @param none
* @return data array NOT FINISHED YET
**/
public function getHashrateForPool($format='array') {
$this->debug->append("STA " . __METHOD__, 4);
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__)) return $data;
$stmt = $this->mysqli->prepare("
SELECT
timestamp,
FROM_UNIXTIME(timestamp, '%Y-%m-%d %T') AS time,
SUM(DISTINCT account_id)
FROM " . $this->getUserStatsTableName() . "
WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY HOUR(FROM_UNIXTIME(timestamp))");
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result()) {
// return json_encode(array(time() * 1000, 1000));
$aData = $result->fetch_all(MYSQLI_ASSOC);
var_dump($aData);
if ($format == 'json') $aData = json_encode($aData);
return $this->memcache->setCache(__FUNCTION__ . $format, $aData);
}
return $this->sqlError();
}
/** /**
* get user estimated payouts based on share counts * get user estimated payouts based on share counts
* @param value1 mixed Round shares OR share rate * @param value1 mixed Round shares OR share rate
@ -931,7 +907,7 @@ class Statistics extends Base {
/** /**
* Purge older entries from our statistics_users table * Purge older entries from our statistics_users table
**/ **/
public function purgeUserStats($days = 7) { public function purgeUserStats($days = 1) {
// Fallbacks if unset // Fallbacks if unset
$stmt = $this->mysqli->prepare("DELETE FROM " . $this->getUserStatsTableName() . " WHERE FROM_UNIXTIME(timestamp) <= DATE_SUB(NOW(), INTERVAL ? DAY)"); $stmt = $this->mysqli->prepare("DELETE FROM " . $this->getUserStatsTableName() . " WHERE FROM_UNIXTIME(timestamp) <= DATE_SUB(NOW(), INTERVAL ? DAY)");
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $days) && $stmt->execute()) if ($this->checkStmt($stmt) && $stmt->bind_param('i', $days) && $stmt->execute())

View File

@ -160,6 +160,13 @@ $aSettings['statistics'][] = array(
'name' => 'statistics_ajax_data_interval', 'value' => $setting->getValue('statistics_ajax_data_interval'), 'name' => 'statistics_ajax_data_interval', 'value' => $setting->getValue('statistics_ajax_data_interval'),
'tooltip' => 'Time in minutes, interval for hashrate and sharerate calculations. Higher intervals allow for better accuracy at a higer server load.' 'tooltip' => 'Time in minutes, interval for hashrate and sharerate calculations. Higher intervals allow for better accuracy at a higer server load.'
); );
$aSettings['statistics'][] = array(
'display' => 'Graphing Days', 'type' => 'text',
'size' => 25,
'default' => 1,
'name' => 'statistics_graphing_days', 'value' => $setting->getValue('statistics_graphing_days'),
'tooltip' => 'How many days to graph out on the statistics -> graphs page.'
);
$aSettings['statistics'][] = array( $aSettings['statistics'][] = array(
'display' => 'Block Statistics Count', 'type' => 'text', 'display' => 'Block Statistics Count', 'type' => 'text',
'size' => 25, 'size' => 25,

View File

@ -4,11 +4,9 @@ $defflip = (!cfip()) ? exit(header('HTTP/1.1 401 Unauthorized')) : 1;
if (!$smarty->isCached('master.tpl', $smarty_cache_key)) { if (!$smarty->isCached('master.tpl', $smarty_cache_key)) {
$debug->append('No cached version available, fetching from backend', 3); $debug->append('No cached version available, fetching from backend', 3);
if ($user->isAuthenticated()) { if ($user->isAuthenticated()) {
$aHourlyHashRates = $statistics->getHashrateByAccount($_SESSION['USERDATA']['id'], 'json'); $aHourlyMiningStats = $statistics->getHourlyMiningStatsByAccount($_SESSION['USERDATA']['id'], 'json', $setting->getValue('statistics_graphing_days', 1));
$aPoolHourlyHashRates = $statistics->getHashrateForPool('json');
} }
$smarty->assign("YOURHASHRATES", @$aHourlyHashRates); $smarty->assign('YOURMININGSTATS', @$aHourlyMiningStats);
$smarty->assign("POOLHASHRATES", @$aPoolHourlyHashRates);
} else { } else {
$debug->append('Using cached page', 3); $debug->append('Using cached page', 3);
} }

View File

@ -1,10 +0,0 @@
{if is_array($YOURHASHRATES) && is_array($POOLHASHRATES)}
<div class="tab-pane fade in" id="both">
<div class="panel-heading">
Your vs. Pool Hashrate
</div>
<div class="panel-body">
<div id="both-area-chart"></div>
</div>
</div>
{/if}

View File

@ -1,47 +1,48 @@
<script> <script>
$(function () { $(function () {
var hashChart = Morris.Line({
element: 'hashrate-area-chart',
data: {$YOURMININGSTATS},
xkey: 'time',
ykeys: ['hashrate'],
labels: ['Hashrate'],
pointSize: 1,
hideHover: 'auto',
resize: true,
fillOpacity: 1.00,
lineColors: ['#24A665'],
pointFillColors: ['#24A665'],
pointStrokeColors: ['#24A665']
});
// needed for automatic activation of first tab var workersChart = Morris.Line({
$(function () { element: 'workers-area-chart',
$('#hashrategraph a:first').tab('show') data: {$YOURMININGSTATS},
}) xkey: 'time',
ykeys: ['workers'],
labels: ['Workers'],
pointSize: 1,
hideHover: 'auto',
resize: true,
fillOpacity: 1.00,
lineColors: ['#24A665'],
pointFillColors: ['#24A665'],
pointStrokeColors: ['#24A665']
});
// You can't draw here chart directly, because it's on hidden tab, instead let's do the workaround var shareCharts= Morris.Line({
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) { element: 'sharerate-area-chart',
if ($(e.target).attr('href') == '#mine' && $('#mine-area-chart').html().length == 0) { data: {$YOURMININGSTATS},
var chart = Morris.Line({ xkey: 'time',
// ID of the element in which to draw the chart. ykeys: ['sharerate'],
element: 'mine-area-chart', labels: ['Sharerate'],
data: {$YOURHASHRATES}, pointSize: 1,
xkey: 'time', hideHover: 'auto',
ykeys: ['hashrate'], resize: true,
labels: ['Hashrate'], fillOpacity: 1.00,
pointSize: 1, lineColors: ['#24A665'],
hideHover: 'auto', pointFillColors: ['#24A665'],
resize: true, pointStrokeColors: ['#24A665']
fillOpacity: 1.00,
lineColors: ['#24A665'],
pointFillColors: ['#24A665'],
pointStrokeColors: ['#24A665']
});
}
if ($(e.target).attr('href') == '#pool' && $('#pool-area-chart').html().length == 0) {
var chart = Morris.Line({
// ID of the element in which to draw the chart.
element: 'pool-area-chart',
data: {$POOLHASHRATES},
xkey: 'time',
ykeys: ['hashrate'],
labels: ['Hashrate'],
pointSize: 1,
hideHover: 'auto',
resize: true,
fillOpacity: 1.00,
lineColors: ['#24A665'],
pointFillColors: ['#24A665'],
pointStrokeColors: ['#24A665']
});
}
}); });
}); });
</script> </script>
@ -50,17 +51,45 @@ $(function () {
<div class="col-lg-12"> <div class="col-lg-12">
<div class="panel panel-info"> <div class="panel panel-info">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-signal fa-fw"></i> Stats <i class="fa fa-signal fa-fw"></i> Average Hashrate past 24h
</div> </div>
<div class="panel-body"> <div class="panel-body">
<ul class="nav nav-pills" id="hashrategraph"> <div id="hashrate-area-chart"></div>
<li><a href="#mine" data-toggle="tab">Mine</a></li> </div>
<li><a href="#pool" data-toggle="tab">Pool</a></li> <div class="panel-footer">
</ul> Your average hashrate per hour, updated every backend cron run.
<div class="tab-content"> </div>
{include file="{$smarty.request.page|escape}/{$smarty.request.action|escape}/mine.tpl"} </div>
{include file="{$smarty.request.page|escape}/{$smarty.request.action|escape}/pool.tpl"} </div>
</div> </div>
<div class="row">
<div class="col-lg-12">
<div class="panel panel-info">
<div class="panel-heading">
<i class="fa fa-signal fa-fw"></i> Average Workers past 24h
</div>
<div class="panel-body">
<div id="workers-area-chart"></div>
</div>
<div class="panel-footer">
Your average active workers per hour, updated every backend cron run.
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="panel panel-info">
<div class="panel-heading">
<i class="fa fa-signal fa-fw"></i> Average Sharerate past 24h
</div>
<div class="panel-body">
<div id="sharerate-area-chart"></div>
</div>
<div class="panel-footer">
Your share rate per hour, updated every backend cron run.
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,8 +0,0 @@
<div class="tab-pane fade in" id="mine">
<div class="panel-heading">
Your Hashrate
</div>
<div class="panel-body">
<div id="mine-area-chart"></div>
</div>
</div>

View File

@ -1,8 +0,0 @@
<div class="tab-pane fade in" id="pool">
<div class="panel-heading">
Pool Hashrate
</div>
<div class="panel-body">
<div id="pool-area-chart"></div>
</div>
</div>