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:
parent
5ff95fb5b2
commit
58b1c1ec56
1 changed files with 175 additions and 119 deletions
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue