use latest playername, flush playernamecache everyday at 1:00, rcon connection recycling, fix crash on disabled dynmap metrics, performance improvements

This commit is contained in:
Joshua Grimm 2020-04-20 11:53:15 +02:00
parent 892de53b52
commit 7d64132ce1
2 changed files with 33 additions and 10 deletions

View file

@ -5,6 +5,7 @@ import json
import nbt import nbt
import re import re
import os import os
import schedule
from mcrcon import MCRcon from mcrcon import MCRcon
from os import listdir from os import listdir
from os.path import isfile, join from os.path import isfile, join
@ -17,20 +18,40 @@ class MinecraftCollector(object):
self.betterquesting = "/world/betterquesting" self.betterquesting = "/world/betterquesting"
self.map = dict() self.map = dict()
self.questsEnabled = False self.questsEnabled = False
self.rcon = None
if os.path.isdir(self.betterquesting): if os.path.isdir(self.betterquesting):
self.questsEnabled = True self.questsEnabled = True
schedule.every().day.at("01:00").do(self.flush_playernamecache)
def get_players(self): def get_players(self):
return [f[:-5] for f in listdir(self.statsdirectory) if isfile(join(self.statsdirectory, f))] return [f[:-5] for f in listdir(self.statsdirectory) if isfile(join(self.statsdirectory, f))]
def flush_playernamecache(self):
print("flushing playername cache")
self.map = dict()
return
def uuid_to_player(self,uuid): def uuid_to_player(self,uuid):
uuid = uuid.replace('-','') uuid = uuid.replace('-','')
if uuid in self.map: if uuid in self.map:
return self.map[uuid] return self.map[uuid]
else: else:
result = requests.get('https://api.mojang.com/user/profiles/'+uuid+'/names') result = requests.get('https://api.mojang.com/user/profiles/'+uuid+'/names')
self.map[uuid] = result.json()[0]['name'] self.map[uuid] = result.json()[-1]['name']
return(result.json()[0]['name']) return(result.json()[-1]['name'])
def rcon_command(self,command):
if self.rcon == None:
self.rcon = MCRcon(os.environ['RCON_HOST'],os.environ['RCON_PASSWORD'],port=int(os.environ['RCON_PORT']))
self.rcon.connect()
try:
response = self.rcon.command(command)
except BrokenPipeError:
print("Lost RCON Connection, trying to reconnect")
self.rcon.connect()
response = self.rcon.command(command)
return response
def get_server_stats(self): def get_server_stats(self):
metrics = [] metrics = []
@ -45,11 +66,9 @@ class MinecraftCollector(object):
metrics.extend([dim_tps,dim_ticktime,overall_tps,overall_ticktime,player_online,entities]) metrics.extend([dim_tps,dim_ticktime,overall_tps,overall_ticktime,player_online,entities])
mcr = MCRcon(os.environ['RCON_HOST'],os.environ['RCON_PASSWORD'],port=int(os.environ['RCON_PORT']))
mcr.connect()
# dimensions # dimensions
resp = mcr.command("forge tps") resp = self.rcon_command("forge tps")
dimtpsregex = re.compile("Dim\s*(-*\d*)\s\((.*?)\)\s:\sMean tick time:\s(.*?) ms\. Mean TPS: (\d*\.\d*)") dimtpsregex = re.compile("Dim\s*(-*\d*)\s\((.*?)\)\s:\sMean tick time:\s(.*?) ms\. Mean TPS: (\d*\.\d*)")
for dimid, dimname, meanticktime, meantps in dimtpsregex.findall(resp): for dimid, dimname, meanticktime, meantps in dimtpsregex.findall(resp):
dim_tps.add_sample('dim_tps',value=meantps,labels={'dimension_id':dimid,'dimension_name':dimname}) dim_tps.add_sample('dim_tps',value=meantps,labels={'dimension_id':dimid,'dimension_name':dimname})
@ -59,13 +78,13 @@ class MinecraftCollector(object):
overall_ticktime.add_sample('overall_ticktime',value=overallregex.findall(resp)[0][0],labels={}) overall_ticktime.add_sample('overall_ticktime',value=overallregex.findall(resp)[0][0],labels={})
# dynmap # dynmap
if os.environ['DYNMAP_ENABLED'] == "True": if 'DYNMAP_ENABLED' in os.environ and os.environ['DYNMAP_ENABLED'] == "True":
dynmap_tile_render_statistics = Metric('dynmap_tile_render_statistics','Tile Render Statistics reported by Dynmap',"counter") dynmap_tile_render_statistics = Metric('dynmap_tile_render_statistics','Tile Render Statistics reported by Dynmap',"counter")
dynmap_chunk_loading_statistics_count = Metric('dynmap_chunk_loading_statistics_count','Chunk Loading Statistics reported by Dynmap',"counter") dynmap_chunk_loading_statistics_count = Metric('dynmap_chunk_loading_statistics_count','Chunk Loading Statistics reported by Dynmap',"counter")
dynmap_chunk_loading_statistics_duration = Metric('dynmap_chunk_loading_statistics_duration','Chunk Loading Statistics reported by Dynmap',"counter") dynmap_chunk_loading_statistics_duration = Metric('dynmap_chunk_loading_statistics_duration','Chunk Loading Statistics reported by Dynmap',"counter")
metrics.extend([dynmap_tile_render_statistics,dynmap_chunk_loading_statistics_count,dynmap_chunk_loading_statistics_duration]) metrics.extend([dynmap_tile_render_statistics,dynmap_chunk_loading_statistics_count,dynmap_chunk_loading_statistics_duration])
resp = mcr.command("dynmap stats") resp = self.rcon_command("dynmap stats")
dynmaptilerenderregex = re.compile(" (.*?): processed=(\d*), rendered=(\d*), updated=(\d*)") dynmaptilerenderregex = re.compile(" (.*?): processed=(\d*), rendered=(\d*), updated=(\d*)")
for dim, processed, rendered, updated in dynmaptilerenderregex.findall(resp): for dim, processed, rendered, updated in dynmaptilerenderregex.findall(resp):
@ -81,13 +100,13 @@ class MinecraftCollector(object):
# entites # entites
resp = mcr.command("forge entity list") resp = self.rcon_command("forge entity list")
entityregex = re.compile("(\d+): (.*?:.*?)\s") entityregex = re.compile("(\d+): (.*?:.*?)\s")
for entitycount, entityname in entityregex.findall(resp): for entitycount, entityname in entityregex.findall(resp):
entities.add_sample('entities',value=entitycount,labels={'entity':entityname}) entities.add_sample('entities',value=entitycount,labels={'entity':entityname})
# player # player
resp = mcr.command("list") resp = self.rcon_command("list")
playerregex = re.compile("There are \d*\/20 players online:(.*)") playerregex = re.compile("There are \d*\/20 players online:(.*)")
if playerregex.findall(resp): if playerregex.findall(resp):
for player in playerregex.findall(resp)[0].split(","): for player in playerregex.findall(resp)[0].split(","):
@ -217,7 +236,9 @@ class MinecraftCollector(object):
def collect(self): def collect(self):
for player in self.get_players(): for player in self.get_players():
for metric in self.update_metrics_for_player(player)+self.get_server_stats(): for metric in self.update_metrics_for_player(player):
yield metric
for metric in self.get_server_stats():
yield metric yield metric
@ -230,3 +251,4 @@ if __name__ == '__main__':
print("Exporter started on Port 8000") print("Exporter started on Port 8000")
while True: while True:
time.sleep(1) time.sleep(1)
schedule.run_pending()

View file

@ -2,3 +2,4 @@ mcrcon==0.5.2
NBT==1.5.0 NBT==1.5.0
prometheus-client==0.7.1 prometheus-client==0.7.1
requests==2.20.0 requests==2.20.0
schedule==0.6.0