Improved cron logging via logfiles

* Added 3rd party logger library KLogger
* Adjusted all cronjobs from verbose output to logging
* Added new logs folder for crons to write to
* Added new .gitignore for logs folder data
* Updated blocks class to only fetch blocks with no share_id
* Adjusted findblocks to use no blocks class method
This commit is contained in:
Sebastian Grewe 2013-07-07 22:04:43 +02:00
parent 2586aca34e
commit 6dc795fd77
14 changed files with 269 additions and 157 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/public/include/config/global.inc.php
/public/templates/compile/*.php
/cronjobs/logs/*.txt

View File

@ -22,10 +22,8 @@ limitations under the License.
// Include all settings and classes
require_once('shared.inc.php');
verbose("Running auto-payouts ...");
if ($bitcoin->can_connect() !== true) {
verbose(" unable to connect to RPC server, exiting\n");
$log->logFatal(" unable to connect to RPC server, exiting\n");
exit(1);
}
@ -36,16 +34,16 @@ $setting->setValue('auto_payout_active', 1);
$users = $user->getAllAutoPayout();
// Quick summary
verbose(" found " . count($users) . " queued payout(s)\n");
$log->logInfo(" found " . count($users) . " queued payout(s)\n");
// Go through users and run transactions
if (! empty($users)) {
verbose("\tUserID\tUsername\tBalance\tThreshold\tAddress\t\t\t\t\tStatus\n\n");
$log->logInfo("\tUserID\tUsername\tBalance\tThreshold\tAddress");
foreach ($users as $aUserData) {
$aBalance = $transaction->getBalance($aUserData['id']);
$dBalance = $aBalance['confirmed'];
verbose("\t" . $aUserData['id'] . "\t" . $aUserData['username'] . "\t" . $dBalance . "\t" . $aUserData['ap_threshold'] . "\t\t" . $aUserData['coin_address'] . "\t");
$log->logInfo("\t" . $aUserData['id'] . "\t" . $aUserData['username'] . "\t" . $dBalance . "\t" . $aUserData['ap_threshold'] . "\t\t" . $aUserData['coin_address']);
// Only run if balance meets threshold and can pay the potential transaction fee
if ($dBalance > $aUserData['ap_threshold'] && $dBalance > $config['txfee']) {
@ -53,7 +51,7 @@ if (! empty($users)) {
try {
$bitcoin->validateaddress($aUserData['coin_address']);
} catch (BitcoinClientException $e) {
verbose("VERIFY FAILED\n");
$log->logError('Failed to verifu this users coin address, skipping payout');
continue;
}
@ -61,7 +59,7 @@ if (! empty($users)) {
try {
$bitcoin->sendtoaddress($aUserData['coin_address'], $dBalance);
} catch (BitcoinClientException $e) {
verbose("SEND FAILED\n");
$log->logError('Failed to send requested balance to coin address, please check payout process');
continue;
}
@ -71,21 +69,15 @@ if (! empty($users)) {
$aMailData['email'] = $user->getUserEmail($user->getUserName($aUserData['id']));
$aMailData['subject'] = 'Auto Payout Completed';
$aMailData['amount'] = $dBalance;
if (!$notification->sendNotification($aUserData['id'], 'auto_payout', $aMailData)) {
verbose("NOTIFY FAILED\n");
} else {
verbose("OK\n");
}
if (!$notification->sendNotification($aUserData['id'], 'auto_payout', $aMailData))
$log->logError('Failed to send notification email to users address: ' . $aMailData['email']);
} else {
verbose("FAILED\n");
$log->logError('Failed to add new Debit_AP transaction in database for user ' . $user->getUserName($aUserData['id']));
}
} else {
verbose("SKIPPED\n");
}
}
} else {
verbose(" no user has configured their AP > 0\n");
$log->logDebug(" no user has configured their AP > 0\n");
}
// Mark this job as inactive

View File

@ -23,33 +23,31 @@ limitations under the License.
require_once('shared.inc.php');
if ( $bitcoin->can_connect() !== true ) {
verbose("Failed to connect to RPC server\n");
$log->logFatal("Failed to connect to RPC server\n");
exit(1);
}
// Fetch all unconfirmed blocks
$aAllBlocks = $block->getAllUnconfirmed($config['confirmations']);
verbose("ID\tBlockhash\tConfirmations\t\n");
$log->logInfo("ID\tBlockhash\tConfirmations");
foreach ($aAllBlocks as $iIndex => $aBlock) {
$aBlockInfo = $bitcoin->query('getblock', $aBlock['blockhash']);
// Fetch this blocks transaction details to find orphan blocks
$aTxDetails = $bitcoin->query('gettransaction', $aBlockInfo['tx'][0]);
verbose($aBlock['id'] . "\t" . $aBlock['blockhash'] . "\t" . $aBlock['confirmations'] . " -> " . $aBlockInfo['confirmations'] . "\t");
$log->logInfo($aBlock['id'] . "\t" . $aBlock['blockhash'] . "\t" . $aBlock['confirmations'] . " -> " . $aBlockInfo['confirmations']);
if ($aTxDetails['details'][0]['category'] == 'orphan') {
// We have an orphaned block, we need to invalidate all transactions for this one
if ($transaction->setOrphan($aBlock['id']) && $block->setConfirmations($aBlock['id'], -1)) {
verbose("ORPHAN\n");
$log->logInfo(" Block marked as orphan");
} else {
verbose("ORPHAN_ERR");
$log->logError(" Block became orphaned but unable to update database entries");
}
continue;
}
if ($aBlock['confirmations'] == $aBlockInfo['confirmations']) {
verbose("SKIPPED\n");
} else if ($block->setConfirmations($aBlock['id'], $aBlockInfo['confirmations'])) {
verbose("UPDATED\n");
} else {
verbose("ERROR\n");
$log->logDebug(' No update needed');
} else if (!$block->setConfirmations($aBlock['id'], $aBlockInfo['confirmations'])) {
$log->logError(' Failed to update block confirmations');
}
}

View File

@ -25,24 +25,22 @@ require_once('shared.inc.php');
// Fetch our last block found from the DB as a starting point
$aLastBlock = @$block->getLast();
$strLastBlockHash = $aLastBlock['blockhash'];
if (!$strLastBlockHash) {
$strLastBlockHash = '';
}
if (!$strLastBlockHash) $strLastBlockHash = '';
// Fetch all transactions since our last block
if ( $bitcoin->can_connect() === true ){
$aTransactions = $bitcoin->query('listsinceblock', $strLastBlockHash);
} else {
verbose("Aborted: " . $bitcoin->can_connect() . "\n");
$log->logFatal('Unable to conenct to RPC server backend');
exit(1);
}
// Nothing to do so bail out
if (empty($aTransactions['transactions'])) {
verbose("No new RPC transactions since last block\n");
$log->logDebug('No new RPC transactions since last block');
} else {
// Table header
verbose("Blockhash\t\tHeight\tAmount\tConfirmations\tDiff\t\tTime\t\t\tStatus\n");
$log->logInfo("Blockhash\t\tHeight\tAmount\tConfirmations\tDiff\t\tTime");
// Let us add those blocks as unaccounted
foreach ($aTransactions['transactions'] as $iIndex => $aData) {
@ -51,29 +49,26 @@ if (empty($aTransactions['transactions'])) {
$config['reward_type'] == 'block' ? $aData['amount'] = $aData['amount'] : $aData['amount'] = $config['reward'];
$aData['height'] = $aBlockInfo['height'];
$aData['difficulty'] = $aBlockInfo['difficulty'];
verbose(substr($aData['blockhash'], 0, 15) . "...\t" .
$log->logInfo(substr($aData['blockhash'], 0, 15) . "...\t" .
$aData['height'] . "\t" .
$aData['amount'] . "\t" .
$aData['confirmations'] . "\t\t" .
$aData['difficulty'] . "\t" .
strftime("%Y-%m-%d %H:%M:%S", $aData['time']) . "\t");
if ( $block->addBlock($aData) ) {
verbose("Added\n");
} else {
verbose("Failed" . "\n");
strftime("%Y-%m-%d %H:%M:%S", $aData['time']));
if (!$block->addBlock($aData) ) {
$log->logFatal('Unable to add this block to database: ' . $aData['height']);
}
}
}
}
verbose("\n");
// Now with our blocks added we can scan for their upstream shares
$aAllBlocks = $block->getAllUnaccounted('ASC');
$aAllBlocks = $block->getAllUnsetShareId('ASC');
if (empty($aAllBlocks)) {
verbose("No new unaccounted blocks found\n");
$log->logDebug('No new blocks without share_id found in database');
} else {
// Loop through our unaccounted blocks
verbose("\nBlock ID\tBlock Height\tAmount\tShare ID\tShares\tFinder\t\t\tStatus\n");
$log->logInfo("Block ID\t\tHeight\tAmount\tShare ID\tShares\tFinder");
foreach ($aAllBlocks as $iIndex => $aBlock) {
if (empty($aBlock['share_id'])) {
// Fetch this blocks upstream ID
@ -81,40 +76,35 @@ if (empty($aAllBlocks)) {
$iCurrentUpstreamId = $share->getUpstreamId();
$iAccountId = $user->getUserId($share->getUpstreamFinder());
} else {
verbose("\nUnable to fetch blocks upstream share. Aborting!\n");
verbose($share->getError() . "\n");
$log->logFatal('Unable to fetch blocks upstream share, aborted:' . $share->getError());
exit;
}
// Fetch share information
if (!$iPreviousShareId = $block->getLastShareId()) {
$iPreviousShareId = 0;
verbose("\nUnable to find highest share ID found so far\n");
verbose("If this is your first block, this is normal\n\n");
$log->logInfo('Unable to find highest share ID found so far, if this is your first block, this is normal.');
}
$iRoundShares = $share->getRoundShares($iPreviousShareId, $iCurrentUpstreamId);
// Store new information
$strStatus = "OK";
if (!$block->setShareId($aBlock['id'], $iCurrentUpstreamId))
$strStatus = "Share ID Failed";
$log->logError('Failed to update share ID in database for block ' . $aBlock['height']);
if (!$block->setFinder($aBlock['id'], $iAccountId))
$strStatus = "Finder Failed";
$log->logError('Failed to update finder account ID in database for block ' . $aBlock['height']);
if (!$block->setShares($aBlock['id'], $iRoundShares))
$strStatus = "Shares Failed";
$log->logError('Failed to update share count in database for block ' . $aBlock['height']);
if ($config['block_bonus'] > 0 && !$transaction->addTransaction($iAccountId, $config['block_bonus'], 'Bonus', $aBlock['id'])) {
$strStatus = "Bonus Failed";
$log->logError('Failed to create Bonus transaction in database for user ' . $user->getUserName($iAccountId) . ' for block ' . $aBlock['height']);
}
verbose(
$log->logInfo(
$aBlock['id'] . "\t\t"
. $aBlock['height'] . "\t\t"
. $aBlock['amount'] . "\t"
. $iCurrentUpstreamId . "\t\t"
. $iRoundShares . "\t"
. "[$iAccountId] " . $user->getUserName($iAccountId) . "\t\t"
. $strStatus
. "\n"
. "[$iAccountId] " . $user->getUserName($iAccountId)
);
// Notify users
@ -125,7 +115,8 @@ if (empty($aAllBlocks)) {
$aMailData['subject'] = 'New Block';
$aMailData['email'] = $user->getUserEmail($user->getUserName($aData['account_id']));
$aMailData['shares'] = $iRoundShares;
$notification->sendNotification($aData['account_id'], 'new_block', $aMailData);
if (!$notification->sendNotification($aData['account_id'], 'new_block', $aMailData))
$log->logError('Failed to notify user of new found block: ' . $user->getUserName($aData['account_id']));
}
}
}

1
cronjobs/logs/README.md Normal file
View File

@ -0,0 +1 @@
Logging directory for cronjobs.

View File

@ -22,51 +22,47 @@ limitations under the License.
// Include all settings and classes
require_once('shared.inc.php');
verbose("Running system notifications\n");
verbose(" IDLE Worker Notifications ...");
$log->logDebug(" IDLE Worker Notifications ...");
// Find all IDLE workers
$aWorkers = $worker->getAllIdleWorkers();
if (empty($aWorkers)) {
verbose(" no idle workers found\n");
$log->logDebug(" no idle workers found\n");
} else {
verbose(" found " . count($aWorkers) . " IDLE workers\n");
$log->logInfo(" found " . count($aWorkers) . " IDLE workers\n");
foreach ($aWorkers as $aWorker) {
$aData = $aWorker;
$aData['username'] = $user->getUserName($aWorker['account_id']);
$aData['subject'] = 'IDLE Worker : ' . $aWorker['username'];
$aData['worker'] = $aWorker['username'];
$aData['email'] = $user->getUserEmail($aData['username']);
verbose(" " . $aWorker['username'] . "...");
if (!$notification->sendNotification($aWorker['account_id'], 'idle_worker', $aData)) {
verbose(" " . $notification->getError() . "\n");
} else {
verbose(" sent\n");
}
$log->logInfo(" " . $aWorker['username'] . "...");
if (!$notification->sendNotification($aWorker['account_id'], 'idle_worker', $aData))
$log->logError(" Failed sending notifications: " . $notification->getError() . "\n");
}
}
verbose(" Reset IDLE Worker Notifications ...");
$log->logDebug(" Reset IDLE Worker Notifications ...");
// We notified, lets check which recovered
$aNotifications = $notification->getAllActive('idle_worker');
if (!empty($aNotifications)) {
verbose(" found " . count($aNotifications) . " active notification(s)\n");
$log->logInfo(" found " . count($aNotifications) . " active notification(s)\n");
foreach ($aNotifications as $aNotification) {
$aData = json_decode($aNotification['data'], true);
$aWorker = $worker->getWorker($aData['id']);
verbose(" " . $aWorker['username'] . " ...");
$log->logInfo(" " . $aWorker['username'] . " ...");
if ($aWorker['active'] == 1) {
if ($notification->setInactive($aNotification['id'])) {
verbose(" updated #" . $aNotification['id'] . " for " . $aWorker['username'] . " as inactive\n");
$log->logInfo(" updated #" . $aNotification['id'] . " for " . $aWorker['username'] . " as inactive\n");
} else {
verbose(" failed to update #" . $aNotification['id'] . " for " . $aWorker['username'] . "\n");
$log->logInfo(" failed to update #" . $aNotification['id'] . " for " . $aWorker['username'] . "\n");
}
} else {
verbose(" still inactive\n");
$log->logInfo(" still inactive\n");
}
}
} else {
verbose(" no active IDLE worker notifications\n");
$log->logDebug(" no active IDLE worker notifications\n");
}
?>

View File

@ -25,7 +25,7 @@ require_once('shared.inc.php');
// Check if we are set as the payout system
if ($config['payout_system'] != 'pps') {
verbose("Please activate this cron in configuration via payout_system = pps\n");
$log->logInfo("Please activate this cron in configuration via payout_system = pps\n");
exit(0);
}
@ -35,7 +35,7 @@ if ( $bitcoin->can_connect() === true ){
if (is_array($dDifficulty) && array_key_exists('proof-of-work', $dDifficulty))
$dDifficulty = $dDifficulty['proof-of-work'];
} else {
verbose("Aborted: " . $bitcoin->can_connect() . "\n");
$log->logFatal("Aborted: " . $bitcoin->can_connect() . "\n");
exit(1);
}
@ -58,7 +58,7 @@ $iLastShareId = $share->getLastInsertedShareId();
// Check for all new shares, we start one higher as our last accounted share to avoid duplicates
$aAccountShares = $share->getSharesForAccounts($iPreviousShareId + 1, $iLastShareId);
verbose("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\tPayout\t\tDonation\tFee\t\tStatus\n");
$log->logInfo("ID\tUsername\tInvalid\tValid\t\tPPS Value\t\tPayout\t\tDonation\tFee");
foreach ($aAccountShares as $aData) {
// Take our valid shares and multiply by per share value
@ -74,60 +74,59 @@ foreach ($aAccountShares as $aData) {
// Calculate donation amount
$aData['donation'] = number_format(round($user->getDonatePercent($user->getUserId($aData['username'])) / 100 * ( $aData['payout'] - $aData['fee']), 8), 8);
verbose($aData['id'] . "\t" .
$log->logInfo($aData['id'] . "\t" .
$aData['username'] . "\t" .
$aData['invalid'] . "\t" .
$aData['valid'] . "\t*\t" .
$pps_value . "\t=\t" .
$aData['payout'] . "\t" .
$aData['donation'] . "\t" .
$aData['fee'] . "\t");
$aData['fee']);
$strStatus = "OK";
// Add new credit transaction
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit_PPS'))
$strStatus = "Transaction Failed";
$log->logError('Failed to add Credit_PPS transaction in database');
// Add new fee debit for this block
if ($aData['fee'] > 0 && $config['fees'] > 0)
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee_PPS'))
$strStatus = "Fee Failed";
$log->logError('Failed to add Fee_PPS transaction in database');
// Add new donation debit
if ($aData['donation'] > 0)
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation_PPS'))
$strStatus = "Donation Failed";
verbose($strStatus . "\n");
$log->logError('Failed to add Donation_PPS transaction in database');
}
// Store our last inserted ID for the next run
$setting->setValue('pps_last_share_id', $iLastShareId);
verbose("\n\n------------------------------------------------------------------------------------\n\n");
// Fetch all unaccounted blocks
$aAllBlocks = $block->getAllUnaccounted('ASC');
if (empty($aAllBlocks)) {
verbose("No new unaccounted blocks found\n");
$log->logDebug("No new unaccounted blocks found");
}
// Go through blocks and archive/delete shares that have been accounted for
foreach ($aAllBlocks as $iIndex => $aBlock) {
// If we are running through more than one block, check for previous share ID
$iLastBlockShare = @$aAllBlocks[$iIndex - 1]['share_id'] ? @$aAllBlocks[$iIndex - 1]['share_id'] : 0;
if (!is_numeric($aBlock['share_id'])) die("Block " . $aBlock['height'] . " has no share_id associated with it, not going to continue\n");
if (!is_numeric($aBlock['share_id'])) {
$log->logFatal("Block " . $aBlock['height'] . " has no share_id associated with it, not going to continue");
exit(1);
}
// Per account statistics
$aAccountShares = $share->getSharesForAccounts(@$iLastBlockShare, $aBlock['share_id']);
foreach ($aAccountShares as $key => $aData) {
if (!$statistics->updateShareStatistics($aData, $aBlock['id']))
verbose("Failed to update stats for this block on : " . $aData['username'] . "\n");
$log->logError("Failed to update stats for this block on : " . $aData['username']);
}
// Move shares to archive
if ($config['archive_shares'] && $aBlock['share_id'] < $iLastShareId) {
if (!$share->moveArchive($aBlock['share_id'], $aBlock['id'], @$iLastBlockShare))
verbose("Archving failed\n");
$log->logError("Archving failed");
}
// Delete shares
if ($aBlock['share_id'] < $iLastShareId && !$share->deleteAccountedShares($aBlock['share_id'], $iLastBlockShare)) {
verbose("\nERROR : Failed to delete accounted shares from " . $aBlock['share_id'] . " to " . $iLastBlockShare . ", aborting!\n");
$log->logFatal("Failed to delete accounted shares from " . $aBlock['share_id'] . " to " . $iLastBlockShare . ", aborting!");
exit(1);
}
// Mark this block as accounted for

View File

@ -24,36 +24,39 @@ require_once('shared.inc.php');
// Check if we are set as the payout system
if ($config['payout_system'] != 'prop') {
verbose("Please activate this cron in configuration via payout_system = prop\n");
$log->logInfo("Please activate this cron in configuration via payout_system = prop");
exit(0);
}
// Fetch all unaccounted blocks
$aAllBlocks = $block->getAllUnaccounted('ASC');
if (empty($aAllBlocks)) {
verbose("No new unaccounted blocks found\n");
$log->logDebug('No new unaccounted blocks found in database');
exit(0);
}
$count = 0;
// Table header for account shares
$log->logInfo("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee");
foreach ($aAllBlocks as $iIndex => $aBlock) {
if (!$aBlock['accounted']) {
$iPreviousShareId = @$aAllBlocks[$iIndex - 1]['share_id'] ? $aAllBlocks[$iIndex - 1]['share_id'] : 0;
$iCurrentUpstreamId = $aBlock['share_id'];
if (!is_numeric($iCurrentUpstreamId)) die("Block " . $aBlock['height'] . " has no share_id associated with it, not going to continue\n");
if (!is_numeric($iCurrentUpstreamId)) {
$log->logFatal("Block " . $aBlock['height'] . " has no share_id associated with it, not going to continue.");
$log->logFatal("Please assign a valid share ID to this block to continue the payout process.");
exit(1);
}
$aAccountShares = $share->getSharesForAccounts($iPreviousShareId, $aBlock['share_id']);
$iRoundShares = $share->getRoundShares($iPreviousShareId, $aBlock['share_id']);
$config['reward_type'] == 'block' ? $dReward = $aBlock['amount'] : $dReward = $config['reward'];
if (empty($aAccountShares)) {
verbose("\nNo shares found for this block: " . $aBlock['height'] . " \n\n");
$log->logFatal('No shares found for this block, aborted: ' . $aBlock['height']);
sleep(2);
continue;
}
// Table header for account shares
verbose("ID\tUsername\tValid\tInvalid\tPercentage\tPayout\t\tDonation\tFee\t\tStatus\n");
// Loop through all accounts that have found shares for this round
foreach ($aAccountShares as $key => $aData) {
// Payout based on shares, PPS system
@ -69,45 +72,40 @@ foreach ($aAllBlocks as $iIndex => $aBlock) {
$aData['donation'] = number_format(round($user->getDonatePercent($user->getUserId($aData['username'])) / 100 * ( $aData['payout'] - $aData['fee']), 8), 8);
// Verbose output of this users calculations
verbose($aData['id'] . "\t" .
$log->logInfo($aData['id'] . "\t" .
$aData['username'] . "\t" .
$aData['valid'] . "\t" .
$aData['invalid'] . "\t" .
$aData['percentage'] . "\t" .
$aData['payout'] . "\t" .
$aData['donation'] . "\t" .
$aData['fee'] . "\t");
$aData['fee']);
$strStatus = "OK";
// Update user share statistics
if (!$statistics->updateShareStatistics($aData, $aBlock['id']))
$strStatus = "Stats Failed";
$log->logFatal('Failed to update share statistics for ' . $aData['username']);
// Add new credit transaction
if (!$transaction->addTransaction($aData['id'], $aData['payout'], 'Credit', $aBlock['id']))
$strStatus = "Transaction Failed";
$log->logFatal('Failed to insert new Credit transaction to database for ' . $aData['username']);
// Add new fee debit for this block
if ($aData['fee'] > 0 && $config['fees'] > 0)
if (!$transaction->addTransaction($aData['id'], $aData['fee'], 'Fee', $aBlock['id']))
$strStatus = "Fee Failed";
$log->logFatal('Failed to insert new Fee transaction to database for ' . $aData['username']);
// Add new donation debit
if ($aData['donation'] > 0)
if (!$transaction->addTransaction($aData['id'], $aData['donation'], 'Donation', $aBlock['id']))
$strStatus = "Donation Failed";
verbose("\t$strStatus\n");
$log->logFatal('Failed to insert new Donation transaction to database for ' . $aData['username']);
}
// Move counted shares to archive before this blockhash upstream share
if ($config['archive_shares']) $share->moveArchive($iCurrentUpstreamId, $aBlock['id'], $iPreviousShareId);
// Delete all accounted shares
if (!$share->deleteAccountedShares($iCurrentUpstreamId, $iPreviousShareId)) {
verbose("\nERROR : Failed to delete accounted shares from $iPreviousShareId to $iCurrentUpstreamId, aborting!\n");
$log->logFatal('Failed to delete accounted shares from ' . $iPreviousShareId . ' to ' . $iCurrentUpstreamId . ', aborted');
exit(1);
}
// Mark this block as accounted for
if (!$block->setAccounted($aBlock['id'])) {
verbose("\nERROR : Failed to mark block as accounted! Aborting!\n");
}
verbose("------------------------------------------------------------------------\n\n");
if (!$block->setAccounted($aBlock['id']))
$log->logFatal('Failed to mark block as accounted! Aborted.');
}
}

View File

@ -31,16 +31,7 @@ require_once(BASEPATH . 'include/config/global.inc.php');
// We include all needed files here, even though our templates could load them themself
require_once(INCLUDE_DIR . '/autoloader.inc.php');
// Parse command line
$options = getopt("v");
if (array_key_exists('v', $options)) {
define("VERBOSE", true);
} else {
define("VERBOSE", false);
}
// Command line cron functions only
function verbose($msg) {
if (VERBOSE) echo $msg;
}
// Load 3rd party logging library for running crons
$log = new KLogger ( 'logs/' . basename($_SERVER['PHP_SELF'], '.php') . '.txt' , KLogger::DEBUG );
$log->LogDebug('Starting ' . basename($_SERVER['PHP_SELF'], '.php'));
?>

View File

@ -25,44 +25,34 @@ require_once('shared.inc.php');
// Fetch all cachable values but disable fetching from cache
$statistics->setGetCache(false);
// Verbose output
verbose("Running statistical cache updates\n");
// Since fetching from cache is disabled, overwrite our stats
verbose(" getRoundShares ...");
$start = microtime(true);
if (!$statistics->getRoundShares())
verbose(" update failed");
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
verbose(" getTopContributors shares ...");
$log->logError("getRoundShares update failed");
$log->logInfo("getRoundShares update " . number_format(microtime(true) - $start, 2) . " seconds");
$start = microtime(true);
if (!$statistics->getTopContributors('shares'))
verbose(" update failed");
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
verbose(" getTopContributors hashes ...");
$log->logError("getTopContributors shares update failed");
$log->logInfo("getTopContributors shares " . number_format(microtime(true) - $start, 2) . " seconds");
$start = microtime(true);
if (!$statistics->getTopContributors('hashes'))
verbose(" update failed");
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
verbose(" getCurrentHashrate ...");
$log->logError("getTopContributors hashes update failed");
$log->logInfo("getTopContributors hashes " . number_format(microtime(true) - $start, 2) . " seconds");
$start = microtime(true);
if (!$statistics->getCurrentHashrate())
verbose(" update failed");
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
$log->logError("getCurrentHashrate update failed");
$log->logInfo("getCurrentHashrate " . number_format(microtime(true) - $start, 2) . " seconds");
// Admin specific statistics, we cache the global query due to slowness
verbose(" getAllUserStats ...");
$start = microtime(true);
if (!$statistics->getAllUserStats('%'))
verbose(" update failed");
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds\n");
$log->logError("getAllUserStats update failed");
$log->logInfo("getAllUserStats " . number_format(microtime(true) - $start, 2) . " seconds");
// Per user share statistics based on all shares submitted
verbose(" getAllUserShares ...");
$start = microtime(true);
$aUserShares = $statistics->getAllUserShares();
verbose(" " . number_format(microtime(true) - $start, 2) . " seconds");
$log->logInfo("getAllUserShares " . number_format(microtime(true) - $start, 2) . " seconds");
foreach ($aUserShares as $aShares) {
$memcache->setCache('getUserShares'. $aShares['id'], $aShares);
}
verbose("\n");
?>

View File

@ -25,14 +25,12 @@ require_once('shared.inc.php');
// Include additional file not set in autoloader
require_once(CLASS_DIR . '/tools.class.php');
verbose("Running scheduled updates\n");
verbose(" Price API Call ... ");
if ($price = $tools->getPrice()) {
verbose("found $price as price\n");
$log->logInfo("Price update: found $price as price");
if (!$setting->setValue('price', $price))
verbose("unable to update value in settings table\n");
$log->logError("unable to update value in settings table");
} else {
verbose("failed to fetch API data: " . $tools->getError() . "\n");
$log->logFatal("failed to fetch API data: " . $tools->getError());
}
?>

View File

@ -17,6 +17,7 @@ require_once(CLASS_DIR . '/debug.class.php');
require_once(CLASS_DIR . '/bitcoin.class.php');
require_once(CLASS_DIR . '/statscache.class.php');
require_once(CLASS_DIR . '/bitcoinwrapper.class.php');
require_once(INCLUDE_DIR . '/lib/KLogger.php');
require_once(INCLUDE_DIR . '/database.inc.php');
require_once(INCLUDE_DIR . '/smarty.inc.php');
// Load classes that need the above as dependencies

View File

@ -55,6 +55,18 @@ class Block {
return false;
}
/**
* Fetch all blocks without a share ID
* @param order string Sort order, default ASC
* @return data array Array with database fields as keys
**/
public function getAllUnsetShareId($order='ASC') {
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE ISNULL(share_id) ORDER BY height $order");
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
return false;
}
/**
* Fetch all unaccounted blocks
* @param order string Sort order, default ASC
@ -62,12 +74,8 @@ class Block {
**/
public function getAllUnaccounted($order='ASC') {
$stmt = $this->mysqli->prepare("SELECT * FROM $this->table WHERE accounted = 0 ORDER BY height $order");
if ($this->checkStmt($stmt)) {
$stmt->execute();
$result = $stmt->get_result();
$stmt->close();
if ($this->checkStmt($stmt) && $stmt->execute() && $result = $stmt->get_result())
return $result->fetch_all(MYSQLI_ASSOC);
}
return false;
}

148
public/include/lib/KLogger.php Executable file
View File

@ -0,0 +1,148 @@
<?php
/* Finally, A light, permissions-checking logging class.
*
* Author : Kenneth Katzgrau < katzgrau@gmail.com >
* Date : July 26, 2008
* Comments : Originally written for use with wpSearch
* Website : http://codefury.net
* Version : 1.0
*
* Usage:
* $log = new KLogger ( "log.txt" , KLogger::INFO );
* $log->LogInfo("Returned a million search results"); //Prints to the log file
* $log->LogFATAL("Oh dear."); //Prints to the log file
* $log->LogDebug("x = 5"); //Prints nothing due to priority setting
*/
class KLogger
{
const DEBUG = 1; // Most Verbose
const INFO = 2; // ...
const WARN = 3; // ...
const ERROR = 4; // ...
const FATAL = 5; // Least Verbose
const OFF = 6; // Nothing at all.
const LOG_OPEN = 1;
const OPEN_FAILED = 2;
const LOG_CLOSED = 3;
/* Public members: Not so much of an example of encapsulation, but that's okay. */
public $Log_Status = KLogger::LOG_CLOSED;
public $DateFormat = "Y-m-d G:i:s";
public $MessageQueue;
private $log_file;
private $priority = KLogger::INFO;
private $file_handle;
public function __construct( $filepath , $priority )
{
if ( $priority == KLogger::OFF ) return;
$this->log_file = $filepath;
$this->MessageQueue = array();
$this->priority = $priority;
if ( file_exists( $this->log_file ) )
{
if ( !is_writable($this->log_file) )
{
$this->Log_Status = KLogger::OPEN_FAILED;
$this->MessageQueue[] = "The file exists, but could not be opened for writing. Check that appropriate permissions have been set.";
return;
}
}
if ( $this->file_handle = fopen( $this->log_file , "a" ) )
{
$this->Log_Status = KLogger::LOG_OPEN;
$this->MessageQueue[] = "The log file was opened successfully.";
}
else
{
$this->Log_Status = KLogger::OPEN_FAILED;
$this->MessageQueue[] = "The file could not be opened. Check permissions.";
}
return;
}
public function __destruct()
{
if ( $this->file_handle )
fclose( $this->file_handle );
}
public function LogInfo($line)
{
$this->Log( $line , KLogger::INFO );
}
public function LogDebug($line)
{
$this->Log( $line , KLogger::DEBUG );
}
public function LogWarn($line)
{
$this->Log( $line , KLogger::WARN );
}
public function LogError($line)
{
$this->Log( $line , KLogger::ERROR );
}
public function LogFatal($line)
{
$this->Log( $line , KLogger::FATAL );
}
public function Log($line, $priority)
{
if ( $this->priority <= $priority )
{
$status = $this->getTimeLine( $priority );
$this->WriteFreeFormLine ( "$status $line \n" );
}
}
public function WriteFreeFormLine( $line )
{
if ( $this->Log_Status == KLogger::LOG_OPEN && $this->priority != KLogger::OFF )
{
if (fwrite( $this->file_handle , $line ) === false) {
$this->MessageQueue[] = "The file could not be written to. Check that appropriate permissions have been set.";
}
}
}
private function getTimeLine( $level )
{
$time = date( $this->DateFormat );
switch( $level )
{
case KLogger::INFO:
return "$time - INFO -->";
case KLogger::WARN:
return "$time - WARN -->";
case KLogger::DEBUG:
return "$time - DEBUG -->";
case KLogger::ERROR:
return "$time - ERROR -->";
case KLogger::FATAL:
return "$time - FATAL -->";
default:
return "$time - LOG -->";
}
}
}
?>