2
0
Fork 0
mirror of https://github.com/munin-monitoring/contrib.git synced 2018-11-08 00:59:34 +01:00

Updates as suggested, fix of worker data view, new symlink structure to support multiple addresses

This commit is contained in:
Ralf Geschke 2017-07-12 12:55:51 +02:00
parent 5ff95fb5b2
commit 58b1c1ec56

View file

@ -2,14 +2,36 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# vim: set fileencoding=utf-8 # vim: set fileencoding=utf-8
""" """
=head1 NAME =head1 NAME
nanopool_ - Munin plugin to monitor nanopool eth user data. nanopool_ - Munin plugin to monitor nanopool ethereum user data.
=head1 CONFIGURATION
[nanopool_*]
- Copy to /usr/share/munin/plugins
- Create symlinks in /etc/munin/plugins to nanopool_<graph type>_<account_address>,
e.g. ln -s /usr/share/munin/plugins/nanopool_ /etc/munin/plugins/nanopool_hashrate_0x1234567890abcdef1234567890
Please use the account address in the format "0x<address>".
- To enable graphs, link to one or more of the graph types available
- Then restart munin-node
Graph types and their links:
balance: link to nanopool_balance Show current balance
hashrate: link to nanopool_hashrate Show current calculated hashrate
avghashrate: link to nanopool_avghashrate Show average hashrate of last hour
worker: link to nanopool_worker Show worker data
Thanks to the authors of other Python munin plugins. I've used some of
them as inspiring example.
=head1 VERSION =head1 VERSION
0.0.1 1.0.0
=head1 AUTHOR =head1 AUTHOR
L<Ralf Geschke|https://github.com/geschke> L<Ralf Geschke|https://github.com/geschke>
@ -29,171 +51,205 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
=head1 CONFIGURATION
- Copy to /usr/share/munin/plugins
- Create symlinks in /etc/munin/plugins to nanopool_<graph type>,
e.g. ln -s /usr/share/munin/plugins/nanopool_ /etc/munin/plugins/nanopool_hashrate
- To enable graphs, link to one or more of the graph types available
- Then restart munin-node
Graph types and their links:
balance: link to nanopool_balance Show current balance
hashrate: link to nanopool_hashrate Show current calculated hashrate
avghashrate: link to nanopool_avghashrate Show average hashrate of last hour
worker: link to nanopool_worker Show worker data
Configuration parameters:
env.account_address - the address of the account in form "0x<address>"
Thanks to the authors of other Python munin plugins. I've used some of
them as inspiring example.
=head1 MAGIC MARKERS =head1 MAGIC MARKERS
#%# family=contrib #%# family=contrib
#%# capabilities=autoconf suggest #%# capabilities=suggest
=cut
""" """
from __future__ import print_function
import os import os
import sys import sys
import json import json
try: try:
from urllib.request import Request, urlopen # Python 3 # Python 3
from urllib.request import Request
from urllib.request import urlopen
except: except:
from urllib2 import Request, urlopen # Python 2 # Python 2
from urllib2 import Request
from urllib2 import urlopen
def define_graph_types():
graph_types = {
"balance" : [
{
"title" : "Balance of {0}".format(account_address),
"type" : "GAUGE",
"args" : "--base 1000 -l 0",
"fields" : ["ETH"],
"scale": "no",
"info": "Balance in ETH"
}
],
"hashrate" : [
{
"title" : "Hashrate of {0}".format(account_address),
"type" : "GAUGE",
"args" : "--base 1000 -l 0",
"fields" : ["hashrate"],
"info": "Current Calculated Hashrate in Mh/s"
}
],
"avghashrate" : [
{
"title" : "Average Hashrate of {0}".format(account_address),
"type" : "GAUGE",
"args" : "--base 1000 -l 0",
"fields" : ["avg_hashrate"],
"info": "Average Hashrate of last hour in Mh/s"
GRAPH_TYPES = { }
"balance" : [ ],
{ "worker" : [
"title" : "Balance", {
"type" : "GAUGE", "title" : "Worker"
"args" : "--base 1000 -l 0", }
"fields" : ["ETH"], ]
"scale": "no", }
"info": "Balance in ETH" return graph_types
}
],
"hashrate" : [
{
"title" : "Hashrate",
"type" : "GAUGE",
"args" : "--base 1000 -l 0",
"fields" : ["hashrate"],
"info": "Current Calculated Hashrate in Mh/s"
}
],
"avghashrate" : [
{
"title" : "Average Hashrate",
"type" : "GAUGE",
"args" : "--base 1000 -l 0",
"fields" : ["avg_hashrate"],
"info": "Average Hashrate of last hour in Mh/s"
}
],
"worker" : [
{
"title" : "Worker"
}
]
}
def request_data(): def request_data():
try: url = "https://api.nanopool.org/v1/eth/user/{0}".format(account_address)
address = os.environ["account_address"]
except KeyError:
raise Exception("Environment variable account_address not found, please configure!")
url = 'https://api.nanopool.org/v1/eth/user/' + address
req = Request(url) req = Request(url)
req.add_header('User-Agent', 'Nozilla/5.0') # this fake is necessary to get values, otherwise the request ends in a 403 error # this fake is necessary to get values, otherwise the request ends in a 403 error
txt = urlopen(req).read() req.add_header('User-Agent', 'Nozilla/5.0')
try:
txt = urlopen(req).read()
except Exception as err:
# there could be different exceptions like ValueError, URLError, HTTPError
print("API request error: {0}". format(err), file=sys.stderr)
exit(1)
return json.loads(txt.decode("utf-8")) return json.loads(txt.decode("utf-8"))
def write_config_worker(): def write_config_worker():
data = request_data() data = request_data()
worker_data = data["data"]["workers"] worker_data = sorted(data["data"]["workers"], key=lambda element: element["id"])
print("multigraph worker_hashrate") print("multigraph worker_hashrate_{0}".format(account_address))
print("graph_title Hashrate in Mh/s per worker") print("graph_title Hashrate in Mh/s per worker ({0})".format(account_address))
print("graph_args --base 1000 -l 0") print("graph_args --base 1000 -l 0")
print("graph_vlabel Mh/s") print("graph_vlabel Mh/s")
print("graph_category other") print("graph_category other")
print("graph_width 400")
print("graph_scale no") print("graph_scale no")
for i, val in enumerate(worker_data): for i, val in enumerate(worker_data):
print("worker" + str(i) + "_hashrate.label " + str(val["id"])) worker_name = "_".join(val["id"].split())
print("worker" + str(i) + "_hashrate.type GAUGE") print("worker_{0}_hashrate.label {1}".format(worker_name, str(val["id"])))
print("worker" + str(i) + "_hashrate.info Hashrate of worker '" + str(val["id"]) + "'") print("worker_{0}_hashrate.type GAUGE".format(worker_name))
print("worker" + str(i) + "_hashrate.min 0") print("worker_{0}_hashrate.info Hashrate of worker '{1}'".format(worker_name, str(val["id"])))
print("worker" + str(i) + "_hashrate.draw LINE1") print("worker_{0}_hashrate.min 0".format(worker_name))
print("worker_{0}_hashrate.draw LINE1".format(worker_name))
for val in worker_data:
print("")
worker_name = "_".join(val["id"].split())
print("multigraph worker_hashrate_{0}.worker_{1}".format(account_address, worker_name))
print("graph_title Hashrate in Mh/s of worker {0}".format(worker_name))
print("graph_args --base 1000 -l 0")
print("graph_vlabel Mh/s")
print("graph_category other")
print("graph_scale no")
print("whashrate.label hashrate")
print("whashrate.type GAUGE")
print("whashrate.info Hashrate of worker {0}".format(str(val["id"])))
print("whashrate.min 0")
print("whashrate.draw LINE1")
print("") print("")
print("multigraph worker_shares") print("multigraph worker_shares_{0}".format(account_address))
print("graph_title Number of accepted shares") print("graph_title Number of accepted shares ({0})".format(account_address))
print("graph_args --base 1000 -l 0") print("graph_args --base 1000 -l 0")
print("graph_vlabel Shares per ${graph_period}") print("graph_vlabel Shares per ${graph_period}")
print("graph_category other") print("graph_category other")
print("graph_width 400")
print("graph_scale no") print("graph_scale no")
print("graph_period minute") print("graph_period minute")
for i, val in enumerate(worker_data): for i, val in enumerate(worker_data):
print("worker" + str(i) + "_shares.label " + str(val["id"])) worker_name = "_".join(val["id"].split())
print("worker" + str(i) + "_shares.type COUNTER") print("worker_{0}_shares.label {1} ".format(worker_name, str(val["id"])))
print("worker" + str(i) + "_shares.info Accepted shares of worker '" + str(val["id"]) + "'") print("worker_{0}_shares.type COUNTER".format(worker_name))
print("worker" + str(i) + "_shares.min 0") print("worker_{0}_shares.info Accepted shares of worker '{1}'".format(worker_name, str(val["id"])))
print("worker" + str(i) + "_shares.draw LINE1") print("worker_{0}_shares.min 0".format(worker_name))
print("worker_{0}_shares.draw LINE1".format(worker_name))
for val in worker_data:
worker_name = "_".join(val["id"].split())
print("")
print("multigraph worker_shares_{0}.worker_{1}".format(account_address, worker_name))
print("graph_title Number of accepted shares {0}".format(worker_name))
print("graph_args --base 1000 -l 0")
print("graph_vlabel Shares per ${graph_period}")
print("graph_category other")
print("graph_scale no")
print("graph_period minute")
print("wshares.label shares")
print("wshares.type COUNTER")
print("wshares.info Accepted shares of worker '{0}'".format(str(val["id"])))
print("wshares.min 0")
print("wshares.draw LINE1")
def write_data_worker(data): def write_data_worker(data):
worker_data = data["data"]["workers"] worker_data = sorted(data["data"]["workers"], key=lambda element: element["id"])
print("multigraph worker_hashrate") print("multigraph worker_hashrate_{0}".format(account_address))
for i, val in enumerate(worker_data):
print("worker" + str(i) + "_hashrate.value " + str(val["hashrate"]))
print
print("multigraph worker_shares")
for i, val in enumerate(worker_data): for i, val in enumerate(worker_data):
print("worker" + str(i) + "_shares.value " + str(val["rating"])) worker_name = "_".join(val["id"].split())
print("worker_{0}_hashrate.value {1}".format(worker_name, str(val["hashrate"])))
for val in worker_data:
print("")
worker_name = "_".join(val["id"].split())
print("multigraph worker_hashrate_{0}.worker_{1}".format(account_address, worker_name))
print("whashrate.value {0}".format(str(val["hashrate"])))
print("")
print("multigraph worker_shares_{0}".format(account_address))
for i, val in enumerate(worker_data):
worker_name = "_".join(val["id"].split())
print("worker_{0}_shares.value {1}".format(worker_name, str(val["rating"])))
for val in worker_data:
worker_name = "_".join(val["id"].split())
print("")
print("multigraph worker_shares_{0}.worker_{1}".format(account_address, worker_name))
print("wshares.value {0} ".format(str(val["rating"])))
def write_config(): def write_config():
if graph_type not in GRAPH_TYPES.keys(): if graph_type not in GRAPH_TYPES.keys():
raise Exception("Unknown graph type '%s'" %graph_type) print("Unknown graph type '{0}'".format(graph_type), file=sys.stderr)
exit(1)
if graph_type == "worker": if graph_type == "worker":
write_config_worker() write_config_worker()
return return
params = GRAPH_TYPES[graph_type] params = GRAPH_TYPES[graph_type]
for item in params: for item in params:
print("graph_title %s" % item["title"]) print("graph_title {0}".format(item["title"]))
print("graph_category other") print("graph_category other")
if "info" in item: if "info" in item:
print("graph_info %s" % item["info"]) print("graph_info {0}".format(item["info"]))
if "scale" in item: if "scale" in item:
print("graph_scale %s" % item["scale"]) print("graph_scale {0}".format(item["scale"]))
if "args" in item: if "args" in item:
print("graph_args %s" % item["args"]) print("graph_args {0}".format(item["args"]))
for field in item["fields"]: for field in item["fields"]:
print("%s.label %s" % (field, field)) print("{0}.label {1}".format(field, field))
print("%s.type %s" % (field, item["type"])) print("{0}.type {1}".format(field, item["type"]))
def write_suggest(): def write_suggest():
for item in GRAPH_TYPES.keys(): for item in GRAPH_TYPES.keys():
@ -203,32 +259,32 @@ def write_data():
data = request_data() data = request_data()
if graph_type == "balance": if graph_type == "balance":
print("ETH.value %s" % data['data']['balance']) print("ETH.value {0}".format(data['data']['balance']))
elif graph_type == "hashrate": elif graph_type == "hashrate":
print("hashrate.value %s" % data["data"]["hashrate"]) print("hashrate.value {0}".format(data["data"]["hashrate"]))
elif graph_type == "avghashrate": elif graph_type == "avghashrate":
print("avg_hashrate.value %s" % data["data"]["avgHashrate"]["h1"]) print("avg_hashrate.value {0}".format(data["data"]["avgHashrate"]["h1"]))
elif graph_type == "worker": elif graph_type == "worker":
write_data_worker(data) write_data_worker(data)
else:
pass
def check_autoconf():
try:
address = os.environ["account_address"]
print("yes")
except KeyError:
print("no (Environment variable account_address not found, please configure!)")
exit(0)
if __name__ == "__main__": if __name__ == "__main__":
program = sys.argv[0] program = sys.argv[0]
graph_type = program[program.rfind("_")+1:] try:
graph_type, account_address = program.split("_")[1:]
except ValueError:
print("Please configure the plugin as described in the configuration section.")
exit(1)
if len(sys.argv) == 2 and sys.argv[1] == "autoconf": GRAPH_TYPES = define_graph_types()
check_autoconf() if len(sys.argv) > 1 and sys.argv[1] == "autoconf":
elif len(sys.argv) == 2 and sys.argv[1] == "config": print("no")
elif len(sys.argv) > 1 and sys.argv[1] == "config":
write_config() write_config()
elif len(sys.argv) == 2 and sys.argv[1] == "suggest": elif len(sys.argv) > 1 and sys.argv[1] == "suggest":
write_suggest() write_suggest()
else: else:
write_data() write_data()