Skip to content
This repository has been archived by the owner on May 15, 2024. It is now read-only.

Block confirmation times in API #119

Merged
9 commits merged into from
Mar 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions api.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,51 @@
$peers = (array) $rpcPeers->{'peers'};
$data->numPeers = count($peers);

// -- Get confirmation info from nano_node. Average time, blocks used, time span and percentiles
// -- over last X min (set by CONFIRMATION_TIME_LIMIT) or max 2048 blocks which is a node limitation
//$timeStampBefore = microtime(true); // measure execution time
$rpcConfHistory = getConfirmationHistory($ch);
$confirmations = $rpcConfHistory->{'confirmations'}; // a list of last X confirmations {hash,duration,time,tally}
//$confAverage = $rpcConfHistory->{'confirmation_stats'}->{'average'}; // average time [ms] of all confirmations
//$confCount = $rpcConfHistory->{'confirmation_stats'}->{'count'}; // number of confirmations retrieved from the node

// remove data older than $timeLimit
usort($confirmations, 'cmpByTime'); // sort array by time value [ms unix time]
$confCompact = []; // new filtered array
$durationTotal = 0; // for average calc
$confAverage = 0; // average confirmation duration
$timeSpan = 0; // full time span of the data [ms]
foreach ($confirmations as $confirmation) {
// only keep data which is later than X ms from latest (highest) value
if ($confirmation->{'time'} >= $confirmations[0]->{'time'} - CONFIRMATION_TIME_LIMIT) {
array_push($confCompact, $confirmation); // add new data
$durationTotal += $confirmation->{'duration'};
} else {
break; // stop iterating once we pass that limit to save time
}
}
$confCount = count($confCompact);

// calculate duration average and time span, avoid dividing by zero
if ($confCount > 0) {
$confAverage = round($durationTotal / $confCount);
$timeSpan = $confCompact[0]->{'time'} - $confCompact[$confCount - 1]->{'time'}; // first minus last
}

// get percentiles directly from the filtered array
usort($confCompact, 'cmpByDuration'); // sort array by duration value
$percentile50 = getConfirmationsDurationPercentile(50, $confCompact); // 50 percentile also called median
$percentile75 = getConfirmationsDurationPercentile(75, $confCompact);
$percentile90 = getConfirmationsDurationPercentile(90, $confCompact);
$percentile95 = getConfirmationsDurationPercentile(95, $confCompact);
$percentile99 = getConfirmationsDurationPercentile(99, $confCompact);

// combine an array with all confirmation info
$confSummary = ['count' => $confCount, 'timeSpan' => $timeSpan, 'average' => $confAverage, 'percentile50' => $percentile50,
'percentile75' => $percentile75, 'percentile90' => $percentile90, 'percentile95' => $percentile95, 'percentile99' => $percentile99, ];
$data->confirmationInfo = $confSummary;
//$data->apiProcTimeConf = round((microtime(true) - $timeStampBefore) * 1000);

// -- Get node account balance from nano_node
$rpcNodeAccountBalance = getAccountBalance($ch, $nanoNodeAccount);
$data->accBalanceMnano = rawToCurrency($rpcNodeAccountBalance->{'balance'}, $currency);
Expand Down Expand Up @@ -122,6 +167,9 @@
// close curl handle
curl_close($ch);

// calculate total script execution time
$data->apiProcTime = round((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000);

return $data;
});

Expand Down
5 changes: 4 additions & 1 deletion modules/constants.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

// the project version
define('PROJECT_VERSION', '1.4.14');
define('PROJECT_VERSION', '1.5.0');

// project URL
define('PROJECT_URL', 'https://github.com/NanoTools/nanoNodeMonitor');
Expand Down Expand Up @@ -29,3 +29,6 @@

// curl timeout in seconds to connect to ninja (max delay is NINJA_TIMEOUT + NINJA_CONECTTIMEOUT)
define ('NINJA_CONECTTIMEOUT', 2);

// maximum allowed age of data to be part of the block confirmation time percentiles calculation (milliseconds)
define ('CONFIRMATION_TIME_LIMIT', 600000);
26 changes: 26 additions & 0 deletions modules/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -510,3 +510,29 @@ function currencySymbol($currency)
}

}

// sort array by 'duration' sub value
function cmpByDuration($a, $b) {
return $a->{'duration'} - $b->{'duration'};
}

// sort array by 'time' sub value (largest first)
function cmpByTime($a, $b) {
return $b->{'time'} - $a->{'time'};
}

// get a percentile from a sorted json structure which contains sub element values with the name 'duration'
// ex: get_percentile(75, $arr) to get the 75th percentile
function getConfirmationsDurationPercentile($percentile, $array) {
if (empty($array)) {
return 0;
}
$index = ($percentile/100) * count($array);
if (floor($index) == $index) {
$result = ($array[$index-1]->{'duration'} + $array[$index]->{'duration'})/2;
}
else {
$result = $array[floor($index)]->{'duration'};
}
return $result;
}
10 changes: 10 additions & 0 deletions modules/functions_rpc.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,13 @@ function getStats($ch, $type = "counters")
// post curl
return postCurl($ch, $data);
}

// get confirmation history from nano_node
function getConfirmationHistory($ch)
{
// get confirmation history of latest 2048 elections
$data = array("action" => "confirmation_history");

// post curl
return postCurl($ch, $data);
}