Projet

Général

Profil

Révision 58b1c1ec

ID58b1c1ec56f1ddb49de02c60f522425c87462a7f
Parent 5ff95fb5
Enfant e8ff8cf4

Ajouté par Ralf Geschke il y a plus de 8 ans

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

Voir les différences:

plugins/currency/nanopool/nanopool_
2 2
# -*- coding: utf-8 -*-
3 3
# vim: set fileencoding=utf-8
4 4

  
5

  
6 5
"""
7 6
=head1 NAME
8 7

  
9
nanopool_ - Munin plugin to monitor nanopool eth user data.
8
nanopool_ - Munin plugin to monitor nanopool ethereum user data.
9

  
10

  
11
=head1 CONFIGURATION
12

  
13
[nanopool_*]
14

  
15
        - Copy to /usr/share/munin/plugins
16
        - Create symlinks in /etc/munin/plugins to nanopool_<graph type>_<account_address>,
17
          e.g. ln -s /usr/share/munin/plugins/nanopool_ /etc/munin/plugins/nanopool_hashrate_0x1234567890abcdef1234567890
18
          Please use the account address in the format "0x<address>".
19

  
20
        - To enable graphs, link to one or more of the graph types available
21
        - Then restart munin-node
22

  
23
Graph types and their links:
24
        balance: link to nanopool_balance           Show current balance
25
        hashrate: link to nanopool_hashrate         Show current calculated hashrate
26
        avghashrate: link to nanopool_avghashrate   Show average hashrate of last hour
27
        worker: link to nanopool_worker             Show worker data
28

  
29

  
30
Thanks to the authors of other Python munin plugins. I've used some of
31
them as inspiring example.
10 32

  
11 33
=head1 VERSION
12
0.0.1
34
1.0.0
13 35

  
14 36
=head1 AUTHOR
15 37
L<Ralf Geschke|https://github.com/geschke>
......
29 51
You should have received a copy of the GNU General Public License
30 52
along with this program.  If not, see <http://www.gnu.org/licenses/>.
31 53

  
32
=head1 CONFIGURATION
33

  
34
        - Copy to /usr/share/munin/plugins 
35
        - Create symlinks in /etc/munin/plugins to nanopool_<graph type>,
36
          e.g. ln -s /usr/share/munin/plugins/nanopool_ /etc/munin/plugins/nanopool_hashrate
37
        - To enable graphs, link to one or more of the graph types available
38
        - Then restart munin-node
39

  
40
Graph types and their links:
41
        balance: link to nanopool_balance           Show current balance 
42
        hashrate: link to nanopool_hashrate         Show current calculated hashrate
43
        avghashrate: link to nanopool_avghashrate   Show average hashrate of last hour
44
        worker: link to nanopool_worker             Show worker data
45

  
46
Configuration parameters:
47
        env.account_address - the address of the account in form "0x<address>"
48

  
49
Thanks to the authors of other Python munin plugins. I've used some of 
50
them as inspiring example. 
51
        
52

  
53 54
=head1 MAGIC MARKERS
54 55

  
55 56
#%# family=contrib
56
#%# capabilities=autoconf suggest
57

  
57
#%# capabilities=suggest
58 58

  
59
=cut
59 60
"""
60 61

  
62
from __future__ import print_function
61 63

  
62 64
import os
63 65
import sys
64 66
import json
65 67

  
66 68
try:
67
    from urllib.request import Request, urlopen  # Python 3
69
    # Python 3
70
    from urllib.request import Request
71
    from urllib.request import urlopen
68 72
except:
69
    from urllib2 import Request, urlopen  # Python 2
70

  
71

  
72

  
73

  
74
GRAPH_TYPES = {
75
    "balance" : [
76
        {
77
            "title" : "Balance",
78
            "type" : "GAUGE",
79
            "args" : "--base 1000 -l 0",
80
            "fields" : ["ETH"],
81
            "scale": "no",
82
            "info": "Balance in ETH"
83
        }
84
    ],
85
    "hashrate" : [
86
        {
87
            "title" : "Hashrate",
88
            "type" : "GAUGE",
89
            "args" : "--base 1000 -l 0",
90
            "fields" : ["hashrate"],
91
            "info": "Current Calculated Hashrate in Mh/s"
92
        }
93
    ],
94
    "avghashrate" : [
95
        {
96
            "title" : "Average Hashrate",
97
            "type" : "GAUGE",
98
            "args" : "--base 1000 -l 0",
99
            "fields" : ["avg_hashrate"],
100
            "info": "Average Hashrate of last hour in Mh/s"
101

  
102
        }
103
    ],
104
    "worker" : [
105
        {
106
            "title" : "Worker"
107
        }
108
    ]
109
}
73
    # Python 2
74
    from urllib2 import Request
75
    from urllib2 import urlopen
76
   
77

  
78

  
79
def define_graph_types():
80
    graph_types = {
81
        "balance" : [
82
            {
83
                "title" : "Balance of {0}".format(account_address),
84
                "type" : "GAUGE",
85
                "args" : "--base 1000 -l 0",
86
                "fields" : ["ETH"],
87
                "scale": "no",
88
                "info": "Balance in ETH"
89
            }
90
        ],
91
        "hashrate" : [
92
            {
93
                "title" : "Hashrate of {0}".format(account_address),
94
                "type" : "GAUGE",
95
                "args" : "--base 1000 -l 0",
96
                "fields" : ["hashrate"],
97
                "info": "Current Calculated Hashrate in Mh/s"
98
            }
99
        ],
100
        "avghashrate" : [
101
            {
102
                "title" : "Average Hashrate of {0}".format(account_address),
103
                "type" : "GAUGE",
104
                "args" : "--base 1000 -l 0",
105
                "fields" : ["avg_hashrate"],
106
                "info": "Average Hashrate of last hour in Mh/s"
107

  
108
            }
109
        ],
110
        "worker" : [
111
            {
112
                "title" : "Worker"
113
            }
114
        ]
115
    }
116
    return graph_types
110 117

  
111 118

  
112 119
def request_data():
113 120

  
114
    try:
115
        address = os.environ["account_address"]
116
    except KeyError:
117
        raise Exception("Environment variable account_address not found, please configure!")
118

  
119
    url = 'https://api.nanopool.org/v1/eth/user/' + address
121
    url = "https://api.nanopool.org/v1/eth/user/{0}".format(account_address)
120 122

  
121 123
    req = Request(url)
122
    req.add_header('User-Agent', 'Nozilla/5.0') # this fake is necessary to get values, otherwise the request ends in a 403 error
123
    txt = urlopen(req).read()
124
    # this fake is necessary to get values, otherwise the request ends in a 403 error
125
    req.add_header('User-Agent', 'Nozilla/5.0')
126
    try:
127
        txt = urlopen(req).read()
128
    except Exception as err:
129
        # there could be different exceptions like ValueError, URLError, HTTPError
130
        print("API request error: {0}". format(err), file=sys.stderr)
131
        exit(1)
124 132

  
125 133
    return json.loads(txt.decode("utf-8"))
126 134

  
127 135

  
128 136
def write_config_worker():
129 137
    data = request_data()
130
    worker_data = data["data"]["workers"]
138
    worker_data = sorted(data["data"]["workers"], key=lambda element: element["id"])
131 139

  
132
    print("multigraph worker_hashrate")
133
    print("graph_title Hashrate in Mh/s per worker")
140
    print("multigraph worker_hashrate_{0}".format(account_address))
141
    print("graph_title Hashrate in Mh/s per worker ({0})".format(account_address))
134 142
    print("graph_args --base 1000 -l 0")
135 143
    print("graph_vlabel Mh/s")
136 144
    print("graph_category other")
137
    print("graph_width 400")
138 145
    print("graph_scale no")
139 146

  
140 147
    for i, val in enumerate(worker_data):
141
        print("worker" + str(i) + "_hashrate.label " + str(val["id"]))
142
        print("worker" + str(i) + "_hashrate.type GAUGE")
143
        print("worker" + str(i) + "_hashrate.info Hashrate of worker '" + str(val["id"]) + "'")
144
        print("worker" + str(i) + "_hashrate.min 0")
145
        print("worker" + str(i) + "_hashrate.draw LINE1")
148
        worker_name = "_".join(val["id"].split())
149
        print("worker_{0}_hashrate.label {1}".format(worker_name, str(val["id"])))
150
        print("worker_{0}_hashrate.type GAUGE".format(worker_name))
151
        print("worker_{0}_hashrate.info Hashrate of worker '{1}'".format(worker_name, str(val["id"])))
152
        print("worker_{0}_hashrate.min 0".format(worker_name))
153
        print("worker_{0}_hashrate.draw LINE1".format(worker_name))
154
    
155
    for val in worker_data:
156
        print("")
157
        worker_name = "_".join(val["id"].split())
158
        print("multigraph worker_hashrate_{0}.worker_{1}".format(account_address, worker_name))
159
        print("graph_title Hashrate in Mh/s of worker {0}".format(worker_name))
160
        print("graph_args --base 1000 -l 0")
161
        print("graph_vlabel Mh/s")
162
        print("graph_category other")
163
        print("graph_scale no")
164
        print("whashrate.label hashrate")
165
        print("whashrate.type GAUGE")
166
        print("whashrate.info Hashrate of worker {0}".format(str(val["id"])))
167
        print("whashrate.min 0")
168
        print("whashrate.draw LINE1")
146 169

  
147 170
    print("")
148
    print("multigraph worker_shares")
149
    print("graph_title Number of accepted shares")
171
    print("multigraph worker_shares_{0}".format(account_address))
172
    print("graph_title Number of accepted shares ({0})".format(account_address))
150 173
    print("graph_args --base 1000 -l 0")
151 174
    print("graph_vlabel Shares per ${graph_period}")
152 175
    print("graph_category other")
153
    print("graph_width 400")
154 176
    print("graph_scale no")
155 177
    print("graph_period minute")
156 178

  
157 179
    for i, val in enumerate(worker_data):
158
        print("worker" + str(i) + "_shares.label " + str(val["id"]))
159
        print("worker" + str(i) + "_shares.type COUNTER")
160
        print("worker" + str(i) + "_shares.info Accepted shares of worker '" + str(val["id"]) + "'")
161
        print("worker" + str(i) + "_shares.min 0")
162
        print("worker" + str(i) + "_shares.draw LINE1")
180
        worker_name = "_".join(val["id"].split())
181
        print("worker_{0}_shares.label {1} ".format(worker_name, str(val["id"])))
182
        print("worker_{0}_shares.type COUNTER".format(worker_name))
183
        print("worker_{0}_shares.info Accepted shares of worker '{1}'".format(worker_name, str(val["id"])))
184
        print("worker_{0}_shares.min 0".format(worker_name))
185
        print("worker_{0}_shares.draw LINE1".format(worker_name))
186

  
187
    for val in worker_data:
188
        worker_name = "_".join(val["id"].split())
189
        print("")
190
        print("multigraph worker_shares_{0}.worker_{1}".format(account_address, worker_name))
191
        print("graph_title Number of accepted shares {0}".format(worker_name))
192
        print("graph_args --base 1000 -l 0")
193
        print("graph_vlabel Shares per ${graph_period}")
194
        print("graph_category other")
195
        print("graph_scale no")
196
        print("graph_period minute")
197
        print("wshares.label shares")
198
        print("wshares.type COUNTER")
199
        print("wshares.info Accepted shares of worker '{0}'".format(str(val["id"])))
200
        print("wshares.min 0")
201
        print("wshares.draw LINE1")
163 202

  
164 203

  
165 204
def write_data_worker(data):
166
    worker_data = data["data"]["workers"]
205
    worker_data = sorted(data["data"]["workers"], key=lambda element: element["id"])
206

  
207
    print("multigraph worker_hashrate_{0}".format(account_address))
167 208

  
168
    print("multigraph worker_hashrate")
169 209
    for i, val in enumerate(worker_data):
170
        print("worker" + str(i) + "_hashrate.value " + str(val["hashrate"]))
210
        worker_name = "_".join(val["id"].split())
211
        print("worker_{0}_hashrate.value {1}".format(worker_name, str(val["hashrate"])))
171 212

  
172
    print
173
    print("multigraph worker_shares")
213
    for val in worker_data:
214
        print("")
215
        worker_name = "_".join(val["id"].split())
216
        print("multigraph worker_hashrate_{0}.worker_{1}".format(account_address, worker_name))
217
        print("whashrate.value {0}".format(str(val["hashrate"])))
218

  
219
    print("")
220
    print("multigraph worker_shares_{0}".format(account_address))
174 221
    for i, val in enumerate(worker_data):
175
        print("worker" + str(i) + "_shares.value " + str(val["rating"]))
222
        worker_name = "_".join(val["id"].split())
223
        print("worker_{0}_shares.value {1}".format(worker_name, str(val["rating"])))
224

  
225
    for val in worker_data:
226
        worker_name = "_".join(val["id"].split())
227
        print("")
228
        print("multigraph worker_shares_{0}.worker_{1}".format(account_address, worker_name))
229
        print("wshares.value {0} ".format(str(val["rating"])))
230
      
176 231

  
177 232

  
178 233
def write_config():
179 234
    if graph_type not in GRAPH_TYPES.keys():
180
        raise Exception("Unknown graph type '%s'" %graph_type)
235
        print("Unknown graph type '{0}'".format(graph_type), file=sys.stderr)
236
        exit(1)
181 237
    if graph_type == "worker":
182 238
        write_config_worker()
183 239
        return
184 240
    params = GRAPH_TYPES[graph_type]
185 241
    for item in params:
186
        print("graph_title %s" % item["title"])
242
        print("graph_title {0}".format(item["title"]))
187 243
        print("graph_category other")
188 244
        if "info" in item:
189
            print("graph_info %s" % item["info"])
245
            print("graph_info {0}".format(item["info"]))
190 246
        if "scale" in item:
191
            print("graph_scale %s" % item["scale"])
247
            print("graph_scale {0}".format(item["scale"]))
192 248
        if "args" in item:
193
            print("graph_args %s" % item["args"])
249
            print("graph_args {0}".format(item["args"]))
194 250
        for field in item["fields"]:
195
            print("%s.label %s" % (field, field))
196
            print("%s.type %s" % (field, item["type"]))
251
            print("{0}.label {1}".format(field, field))
252
            print("{0}.type {1}".format(field, item["type"]))
197 253

  
198 254
def write_suggest():
199 255
    for item in GRAPH_TYPES.keys():
......
203 259
    data = request_data()
204 260

  
205 261
    if graph_type == "balance":
206
        print("ETH.value %s" % data['data']['balance'])
262
        print("ETH.value {0}".format(data['data']['balance']))
207 263
    elif graph_type == "hashrate":
208
        print("hashrate.value %s" % data["data"]["hashrate"])
264
        print("hashrate.value {0}".format(data["data"]["hashrate"]))
209 265
    elif graph_type == "avghashrate":
210
        print("avg_hashrate.value %s" % data["data"]["avgHashrate"]["h1"])
266
        print("avg_hashrate.value {0}".format(data["data"]["avgHashrate"]["h1"]))
211 267
    elif graph_type == "worker":
212 268
        write_data_worker(data)
269
    else:
270
        pass
213 271

  
214
def check_autoconf():
215
    try:
216
        address = os.environ["account_address"]
217
        print("yes")
218
    except KeyError:
219
        print("no (Environment variable account_address not found, please configure!)")
220
    exit(0)
221 272

  
222 273
if __name__ == "__main__":
223 274

  
224 275
    program = sys.argv[0]
225
    graph_type = program[program.rfind("_")+1:]
226

  
227
    if len(sys.argv) == 2 and sys.argv[1] == "autoconf":
228
        check_autoconf()
229
    elif len(sys.argv) == 2 and sys.argv[1] == "config":
276
    try:
277
        graph_type, account_address = program.split("_")[1:]
278
    except ValueError:
279
        print("Please configure the plugin as described in the configuration section.")
280
        exit(1)
281

  
282
    GRAPH_TYPES = define_graph_types()
283
    if len(sys.argv) > 1 and sys.argv[1] == "autoconf":
284
        print("no")
285
    elif len(sys.argv) > 1 and sys.argv[1] == "config":
230 286
        write_config()
231
    elif len(sys.argv) == 2 and sys.argv[1] == "suggest":
287
    elif len(sys.argv) > 1 and sys.argv[1] == "suggest":
232 288
        write_suggest()
233 289
    else:
234 290
        write_data()

Formats disponibles : Unified diff