[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);
$status = 'OK';
$message = '';
$affected = $statistics->purgeUserStats();
$affected = $statistics->purgeUserStats($setting->getValue('statistics_graphing_days', 1));
if ($affected === false) {
$message = 'Failed to delete entries: ' . $statistics->getCronError();
$status = 'ERROR';

View File

@ -698,19 +698,21 @@ class Statistics extends Base {
* @param $account_id int account id
* @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);
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data;
$stmt = $this->mysqli->prepare("
SELECT
timestamp,
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() . "
WHERE FROM_UNIXTIME(timestamp) >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
WHERE FROM_UNIXTIME(timestamp) >= DATE_SUB(NOW(), INTERVAL $days DAY)
AND account_id = ?
GROUP BY HOUR(FROM_UNIXTIME(timestamp))");
if ($this->checkStmt($stmt) && $stmt->bind_param('i', $account_id ) && $stmt->execute() && $result = $stmt->get_result()) {
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()) {
$aData = $result->fetch_all(MYSQLI_ASSOC);
if ($format == 'json') $aData = json_encode($aData);
return $this->memcache->setCache(__FUNCTION__ . $account_id . $format, $aData);
@ -718,32 +720,6 @@ class Statistics extends Base {
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
* @param value1 mixed Round shares OR share rate
@ -931,7 +907,7 @@ class Statistics extends Base {
/**
* Purge older entries from our statistics_users table
**/
public function purgeUserStats($days = 7) {
public function purgeUserStats($days = 1) {
// Fallbacks if unset
$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())

View File

@ -160,6 +160,13 @@ $aSettings['statistics'][] = array(
'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.'
);
$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(
'display' => 'Block Statistics Count', 'type' => 'text',
'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)) {
$debug->append('No cached version available, fetching from backend', 3);
if ($user->isAuthenticated()) {
$aHourlyHashRates = $statistics->getHashrateByAccount($_SESSION['USERDATA']['id'], 'json');
$aPoolHourlyHashRates = $statistics->getHashrateForPool('json');
$aHourlyMiningStats = $statistics->getHourlyMiningStatsByAccount($_SESSION['USERDATA']['id'], 'json', $setting->getValue('statistics_graphing_days', 1));
}
$smarty->assign("YOURHASHRATES", @$aHourlyHashRates);
$smarty->assign("POOLHASHRATES", @$aPoolHourlyHashRates);
$smarty->assign('YOURMININGSTATS', @$aHourlyMiningStats);
} else {
$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>
$(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
$(function () {
$('#hashrategraph a:first').tab('show')
})
var workersChart = Morris.Line({
element: 'workers-area-chart',
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
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
if ($(e.target).attr('href') == '#mine' && $('#mine-area-chart').html().length == 0) {
var chart = Morris.Line({
// ID of the element in which to draw the chart.
element: 'mine-area-chart',
data: {$YOURHASHRATES},
xkey: 'time',
ykeys: ['hashrate'],
labels: ['Hashrate'],
pointSize: 1,
hideHover: 'auto',
resize: true,
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']
});
}
var shareCharts= Morris.Line({
element: 'sharerate-area-chart',
data: {$YOURMININGSTATS},
xkey: 'time',
ykeys: ['sharerate'],
labels: ['Sharerate'],
pointSize: 1,
hideHover: 'auto',
resize: true,
fillOpacity: 1.00,
lineColors: ['#24A665'],
pointFillColors: ['#24A665'],
pointStrokeColors: ['#24A665']
});
});
</script>
@ -50,17 +51,45 @@ $(function () {
<div class="col-lg-12">
<div class="panel panel-info">
<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 class="panel-body">
<ul class="nav nav-pills" id="hashrategraph">
<li><a href="#mine" data-toggle="tab">Mine</a></li>
<li><a href="#pool" data-toggle="tab">Pool</a></li>
</ul>
<div class="tab-content">
{include file="{$smarty.request.page|escape}/{$smarty.request.action|escape}/mine.tpl"}
{include file="{$smarty.request.page|escape}/{$smarty.request.action|escape}/pool.tpl"}
</div>
<div id="hashrate-area-chart"></div>
</div>
<div class="panel-footer">
Your average hashrate 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 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>

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>