New statistics system

This commit is contained in:
Shoghi Cervantes 2015-05-19 20:49:30 +02:00
parent 36ddbf286d
commit cde2d39029
No known key found for this signature in database
GPG Key ID: 78464DB0A7837F89
15 changed files with 175 additions and 65 deletions

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -1711,6 +1711,9 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade
$this->orderChunks(); $this->orderChunks();
$this->sendNextChunk(); $this->sendNextChunk();
$this->server->onPlayerLogin($this);
break; break;
case ProtocolInfo::MOVE_PLAYER_PACKET: case ProtocolInfo::MOVE_PLAYER_PACKET:

View File

@ -226,7 +226,7 @@ class Server{
private $dataPath; private $dataPath;
private $pluginPath; private $pluginPath;
private $lastSendUsage = null; private $uniquePlayers = [];
/** @var QueryHandler */ /** @var QueryHandler */
private $queryHandler; private $queryHandler;
@ -1978,7 +1978,6 @@ class Server{
*/ */
public function shutdown(){ public function shutdown(){
$this->isRunning = false; $this->isRunning = false;
gc_collect_cycles();
} }
public function forceShutdown(){ public function forceShutdown(){
@ -1987,6 +1986,10 @@ class Server{
} }
try{ try{
if(!$this->isRunning()){
$this->sendUsage(SendUsageTask::TYPE_CLOSE);
}
$this->hasStopped = true; $this->hasStopped = true;
$this->shutdown(); $this->shutdown();
@ -2031,6 +2034,8 @@ class Server{
} }
$this->memoryManager->doObjectCleanup(); $this->memoryManager->doObjectCleanup();
gc_collect_cycles();
}catch(\Exception $e){ }catch(\Exception $e){
$this->logger->emergency("Crashed while crashing, killing process"); $this->logger->emergency("Crashed while crashing, killing process");
@kill(getmypid()); @kill(getmypid());
@ -2052,7 +2057,7 @@ class Server{
if($this->getProperty("settings.send-usage", true) !== false){ if($this->getProperty("settings.send-usage", true) !== false){
$this->sendUsageTicker = 6000; $this->sendUsageTicker = 6000;
$this->sendUsage(); $this->sendUsage(SendUsageTask::TYPE_OPEN);
} }
@ -2131,7 +2136,7 @@ class Server{
if($this->isRunning === false){ if($this->isRunning === false){
return; return;
} }
$this->isRunning = false; $this->sendUsage(SendUsageTask::TYPE_CLOSE);
$this->hasStopped = false; $this->hasStopped = false;
ini_set("error_reporting", 0); ini_set("error_reporting", 0);
@ -2182,6 +2187,7 @@ class Server{
//$dump .= "Memory Usage Tracking: \r\n" . chunk_split(base64_encode(gzdeflate(implode(";", $this->memoryStats), 9))) . "\r\n"; //$dump .= "Memory Usage Tracking: \r\n" . chunk_split(base64_encode(gzdeflate(implode(";", $this->memoryStats), 9))) . "\r\n";
$this->forceShutdown(); $this->forceShutdown();
$this->isRunning = false;
@kill(getmypid()); @kill(getmypid());
exit(1); exit(1);
} }
@ -2205,6 +2211,12 @@ class Server{
} }
} }
public function onPlayerLogin(Player $player){
if($this->sendUsageTicker > 0){
$this->uniquePlayers[$player->getUniqueId()] = $player->getUniqueId();
}
}
public function addPlayer($identifier, Player $player){ public function addPlayer($identifier, Player $player){
$this->players[$identifier] = $player; $this->players[$identifier] = $player;
$this->identifiers[spl_object_hash($player)] = $identifier; $this->identifiers[spl_object_hash($player)] = $identifier;
@ -2275,38 +2287,9 @@ class Server{
} }
} }
public function sendUsage(){ public function sendUsage($type = SendUsageTask::TYPE_STATUS){
if($this->lastSendUsage instanceof SendUsageTask){ $this->scheduler->scheduleAsyncTask(new SendUsageTask($this, $type, $this->uniquePlayers));
if(!$this->lastSendUsage->isGarbage()){ //do not call multiple times $this->uniquePlayers = [];
return;
}
}
$plist = "";
foreach($this->getPluginManager()->getPlugins() as $p){
$d = $p->getDescription();
$plist .= str_replace([";", ":"], "", $d->getName()) . ":" . str_replace([";", ":"], "", $d->getVersion()) . ";";
}
$version = new VersionString();
$this->lastSendUsage = new SendUsageTask("https://stats.pocketmine.net/usage.php", [
"serverid" => Binary::readLong(substr(hex2bin(str_replace("-", "", $this->serverID)), 0, 8)),
"port" => $this->getPort(),
"os" => Utils::getOS(),
"name" => $this->getName(),
"memory_total" => $this->getConfigString("memory-limit"), //TODO
"memory_usage" => Utils::getMemoryUsage(),
"php_version" => PHP_VERSION,
"version" => $version->get(true),
"build" => $version->getBuild(),
"mc_version" => \pocketmine\MINECRAFT_VERSION,
"protocol" => \pocketmine\network\protocol\Info::CURRENT_PROTOCOL,
"online" => count($this->players),
"max" => $this->getMaxPlayers(),
"plugins" => $plist,
]);
$this->scheduler->scheduleAsyncTask($this->lastSendUsage);
} }
@ -2438,7 +2421,7 @@ class Server{
if($this->sendUsageTicker > 0 and --$this->sendUsageTicker === 0){ if($this->sendUsageTicker > 0 and --$this->sendUsageTicker === 0){
$this->sendUsageTicker = 6000; $this->sendUsageTicker = 6000;
$this->sendUsage(); $this->sendUsage(SendUsageTask::TYPE_STATUS);
} }
if(($this->tickCounter % 100) === 0){ if(($this->tickCounter % 100) === 0){

View File

@ -18,8 +18,6 @@ settings:
enable-profiling: false enable-profiling: false
#Will only add results when tick measurement is below or equal to given value (default 20) #Will only add results when tick measurement is below or equal to given value (default 20)
profile-report-trigger: 20 profile-report-trigger: 20
#Sends anonymous statistics to create usage reports
send-usage: true
#Number of AsyncTask workers. #Number of AsyncTask workers.
#Used for plugin asynchronous tasks, world generation, compression and web communication. #Used for plugin asynchronous tasks, world generation, compression and web communication.
#Set this approximately to your number of cores. #Set this approximately to your number of cores.
@ -125,7 +123,7 @@ chunk-generation:
#Max. amount of chunks in the waiting queue to be generated #Max. amount of chunks in the waiting queue to be generated
queue-size: 8 queue-size: 8
#Max. amount of chunks in the waiting queue to be populated #Max. amount of chunks in the waiting queue to be populated
population-queue-size: 2 population-queue-size: 8
ticks-per: ticks-per:
animal-spawns: 400 animal-spawns: 400
@ -147,6 +145,11 @@ auto-report:
send-phpinfo: false send-phpinfo: false
host: crash.pocketmine.net host: crash.pocketmine.net
anonymous-statistics:
#Sends anonymous statistics for data aggregation, plugin usage tracking
enabled: true
host: stats.pocketmine.net
auto-updater: auto-updater:
enabled: true enabled: true
on-update: on-update:

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -14,26 +14,140 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */
namespace pocketmine\scheduler; namespace pocketmine\scheduler;
use pocketmine\network\protocol\Info;
use pocketmine\Server;
use pocketmine\utils\Utils; use pocketmine\utils\Utils;
use pocketmine\utils\VersionString;
class SendUsageTask extends AsyncTask{ class SendUsageTask extends AsyncTask{
const TYPE_OPEN = 1;
const TYPE_STATUS = 2;
const TYPE_CLOSE = 3;
public $endpoint; public $endpoint;
public $data; public $data;
public function __construct($endpoint, array $data){ public function __construct(Server $server, $type, $playerList = []){
$this->endpoint = $endpoint; $endpoint = "http://" . $server->getProperty("anonymous-statistics.host", "stats.pocketmine.net") . "/";
$this->data = serialize($data); $path = "post";
$data = [];
$data["uniqueServerId"] = Utils::getServerUniqueId();
$data["uniqueRequestId"] = Utils::dataToUUID(Utils::getServerUniqueId(), microtime(true));
switch($type){
case self::TYPE_OPEN:
$path = "open";
$data["event"] = "open";
$version = new VersionString();
$data["server"] = [
"port" => $server->getPort(),
"software" => $server->getName(),
"fullVersion" => $version->get(true),
"version" => $version->get(),
"build" => $version->getBuild(),
"api" => $server->getApiVersion(),
"minecraftVersion" => $server->getVersion(),
"protocol" => Info::CURRENT_PROTOCOL
];
$data["system"] = [
"operatingSystem" => Utils::getOS(),
"cores" => Utils::getCoreCount(),
"phpVersion" => PHP_VERSION,
"machine" => php_uname("a"),
"release" => php_uname("r"),
"platform" => php_uname("i")
];
$data["players"] = [
"count" => 0,
"limit" => $server->getMaxPlayers()
];
$plugins = [];
foreach($server->getPluginManager()->getPlugins() as $p){
$d = $p->getDescription();
$plugins[$d->getName()] = [
"name" => $d->getName(),
"version" => $d->getVersion(),
"enabled" => $p->isEnabled()
];
}
$data["plugins"] = $plugins;
break;
case self::TYPE_STATUS:
$path = "status";
$data["event"] = "status";
$data["server"] = [
"ticksPerSecond" => $server->getTicksPerSecondAverage(),
"tickUsage" => $server->getTickUsageAverage(),
"ticks" => $server->getTick()
];
//This anonymizes the user ids so they cannot be reversed to the original
foreach($playerList as $k => $v){
$playerList[$k] = Utils::dataToUUID($v);
}
$players = [];
foreach($server->getOnlinePlayers() as $p){
if($p->isOnline()){
$players[] = Utils::dataToUUID($p->getUniqueId());
}
}
$data["players"] = [
"count" => count($players),
"limit" => $server->getMaxPlayers(),
"currentList" => $players,
"historyList" => array_values($playerList)
];
$info = Utils::getMemoryUsage(true);
$data["system"] = [
"mainMemory" => $info[0],
"totalMemory" => $info[1],
"availableMemory" => $info[2],
"threadCount" => Utils::getThreadCount()
];
break;
case self::TYPE_CLOSE:
$path = "close";
$data["event"] = "close";
$data["crashing"] = $server->isRunning();
break;
}
$this->endpoint = $endpoint . $path;
$this->data = json_encode($data/*, JSON_PRETTY_PRINT*/);
} }
public function onRun(){ public function onRun(){
Utils::postURL($this->endpoint, unserialize($this->data)); try{
Utils::postURL($this->endpoint, $this->data, 10, [
"Content-Type: application/json",
"Content-Length: ". strlen($this->data)
]);
}catch(\Exception $e){
}
} }
} }

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -14,7 +14,7 @@
* (at your option) any later version. * (at your option) any later version.
* *
* @author PocketMine Team * @author PocketMine Team
* @link http://www.pocketmine.net/
* *
* *
*/ */

View File

@ -32,6 +32,7 @@ class Utils{
public static $online = true; public static $online = true;
public static $ip = false; public static $ip = false;
public static $os; public static $os;
private static $serverUniqueId = null;
/** /**
* Generates an unique identifier to a callable * Generates an unique identifier to a callable
@ -78,6 +79,10 @@ class Utils{
* @return string * @return string
*/ */
public static function getServerUniqueId($extra = ""){ public static function getServerUniqueId($extra = ""){
if(self::$serverUniqueId !== null){
return self::$serverUniqueId;
}
$machine = php_uname("a"); $machine = php_uname("a");
$machine .= file_exists("/proc/cpuinfo") ? implode(preg_grep("/model name/", file("/proc/cpuinfo"))) : ""; $machine .= file_exists("/proc/cpuinfo") ? implode(preg_grep("/model name/", file("/proc/cpuinfo"))) : "";
$machine .= sys_get_temp_dir(); $machine .= sys_get_temp_dir();
@ -114,7 +119,7 @@ class Utils{
$data .= $ext . ":" . phpversion($ext); $data .= $ext . ":" . phpversion($ext);
} }
return Utils::dataToUUID($machine, $data); return self::$serverUniqueId = Utils::dataToUUID($machine, $data);
} }
/** /**
@ -434,16 +439,17 @@ class Utils{
* *
* @param $page * @param $page
* @param int $timeout default 10 * @param int $timeout default 10
* @param array $extraHeaders
* *
* @return bool|mixed * @return bool|mixed
*/ */
public static function getURL($page, $timeout = 10){ public static function getURL($page, $timeout = 10, array $extraHeaders = []){
if(Utils::$online === false){ if(Utils::$online === false){
return false; return false;
} }
$ch = curl_init($page); $ch = curl_init($page);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0 PocketMine-MP"]); curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge(["User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0 PocketMine-MP"], $extraHeaders));
curl_setopt($ch, CURLOPT_AUTOREFERER, true); curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
@ -464,10 +470,11 @@ class Utils{
* @param $page * @param $page
* @param array|string $args * @param array|string $args
* @param int $timeout * @param int $timeout
* @param array $extraHeaders
* *
* @return bool|mixed * @return bool|mixed
*/ */
public static function postURL($page, $args, $timeout = 10){ public static function postURL($page, $args, $timeout = 10, array $extraHeaders = []){
if(Utils::$online === false){ if(Utils::$online === false){
return false; return false;
} }
@ -481,7 +488,7 @@ class Utils{
curl_setopt($ch, CURLOPT_POSTFIELDS, $args); curl_setopt($ch, CURLOPT_POSTFIELDS, $args);
curl_setopt($ch, CURLOPT_AUTOREFERER, true); curl_setopt($ch, CURLOPT_AUTOREFERER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0 PocketMine-MP"]); curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge(["User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0 PocketMine-MP"], $extraHeaders));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int) $timeout); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int) $timeout);
$ret = curl_exec($ch); $ret = curl_exec($ch);