NEW: Energi Core daemon monitoring, suits other Bitcoin forks (#5894)
* NEW: Energi Core daemon monitoring, suites other Bitcoin forks * Attempt to make Codacy checks happy * Added energid sample configuration, enabled by default * Post-review fixes & revised charts * Added default Energi, Bitcoin and Dash to energid.conf configuration * Fighting with Codacy markdown check * Added energid protocol description comment * Added JSON_RPC_VERSION as module variable * Screw you Codacy markdown * Screw you Codacy Markdown #2 * Screw you Codacy Markdown #3 * Finally, fixed what remark-lint wants * Strict local remark-lint + plugins pass for README.md * Attempt with another remark-lint configuration
Andrey Galkin committed
Apr 27, 2019 at 13:53 UTC
0252ce3dc1a5ad55e955e13ebde01a455020a4ca
6 files changed
+329
collectors/python.d.plugin/Makefile.am
+1
@@ -49,6 +49,7 @@ include dns_query_time/Makefile.inc
49
include dockerd/Makefile.inc
50
include dovecot/Makefile.inc
51
include elasticsearch/Makefile.inc
52
+include energid/Makefile.inc
53
include example/Makefile.inc
54
include exim/Makefile.inc
55
include fail2ban/Makefile.inc
collectors/python.d.plugin/energid/Makefile.inc
new
+13
@@ -0,0 +1,13 @@
1
+# SPDX-License-Identifier: GPL-3.0-or-later
2
+
3
+# THIS IS NOT A COMPLETE Makefile
4
+# IT IS INCLUDED BY ITS PARENT'S Makefile.am
5
+# IT IS REQUIRED TO REFERENCE ALL FILES RELATIVE TO THE PARENT
6
+
7
+# install these files
8
+dist_python_DATA += energid/energid.chart.py
9
+dist_pythonconfig_DATA += energid/energid.conf
10
+
11
+# do not install these files, but include them in the distribution
12
+dist_noinst_DATA += energid/README.md energid/Makefile.inc
13
+
collectors/python.d.plugin/energid/README.md
new
+62
@@ -0,0 +1,62 @@
1
+# energid
2
+
3
+A collector for [Energi Core](https://github.com/energicryptocurrency/energi)
4
+node instance monitoring.
5
+
6
+As Energi Core Gen 1 & 2 are based on the original Bitcoin code and
7
+supports very similar JSON RPC, there is quite high chance the module works
8
+with many others forks including bitcoind itself.
9
+
10
+Introduces several new charts:
11
+
12
+1. **Blockchain Index**
13
+ - blocks
14
+ - headers
15
+
16
+2. **Blockchain Difficulty**
17
+ - diff
18
+
19
+3. **MemPool** in MiB
20
+ - Max
21
+ - Usage
22
+ - TX Size
23
+
24
+4. **Secure Memory** in KiB
25
+ - Total
26
+ - Locked
27
+ - Used
28
+
29
+5. **Network**
30
+ - Connections
31
+
32
+6. **UTXO** (Unspent Transaction Output)
33
+ - UTXO
34
+ - Xfers (related transactions)
35
+
36
+Configuration is needed in most cases of secure deployment to specify RPC
37
+credentials. However, Energi, Bitcoin and Dash daemons are checked on
38
+startup by default.
39
+
40
+It may be desired to increase retry count for production use due to possibly
41
+long daemon startup.
42
+
43
+## Configuration
44
+
45
+Sample:
46
+```yaml
47
+energi:
48
+ host: '127.0.0.1'
49
+ port: 9796
50
+ user: energi
51
+ pass: energi
52
+
53
+bitcoin:
54
+ host: '127.0.0.1'
55
+ port: 8332
56
+ user: bitcoin
57
+ pass: bitcoin
58
+```
59
+
60
+---
61
+
62
+[]()
collectors/python.d.plugin/energid/energid.chart.py
new
+162
@@ -0,0 +1,162 @@
1
+# -*- coding: utf-8 -*-
2
+# Description: Energi Core / Bitcoin netdata python.d module
3
+# Author: Andrey Galkin <andrey@futoin.org> (andvgal)
4
+# SPDX-License-Identifier: GPL-3.0-or-later
5
+#
6
+# This module is designed for energid, but it should work with many other Bitcoin forks
7
+# which support more or less standard JSON-RPC.
8
+#
9
+
10
+import json
11
+
12
+from bases.FrameworkServices.UrlService import UrlService
13
+
14
+update_every = 5
15
+
16
+ORDER = [
17
+ 'blockindex',
18
+ 'difficulty',
19
+ 'mempool',
20
+ 'secmem',
21
+ 'network',
22
+ 'timeoffset',
23
+ 'utxo',
24
+ 'xfers',
25
+]
26
+
27
+CHARTS = {
28
+ 'blockindex': {
29
+ 'options': [None, 'Blockchain Index', 'count', 'blockchain', 'energi.blockindex', 'area'],
30
+ 'lines': [
31
+ ['blockchain_blocks', 'blocks', 'absolute'],
32
+ ['blockchain_headers', 'headers', 'absolute'],
33
+ ]
34
+ },
35
+ 'difficulty': {
36
+ 'options': [None, 'Blockchain Difficulty', 'difficulty', 'blockchain', 'energi.difficulty', 'line'],
37
+ 'lines': [
38
+ ['blockchain_difficulty', 'Diff', 'absolute'],
39
+ ],
40
+ },
41
+ 'mempool': {
42
+ 'options': [None, 'MemPool', 'MiB', 'memory', 'energid.mempool', 'area'],
43
+ 'lines': [
44
+ ['mempool_max', 'Max', 'absolute', None, 1024*1024],
45
+ ['mempool_current', 'Usage', 'absolute', None, 1024*1024],
46
+ ['mempool_txsize', 'TX Size', 'absolute', None, 1024*1024],
47
+ ],
48
+ },
49
+ 'secmem': {
50
+ 'options': [None, 'Secure Memory', 'KiB', 'memory', 'energid.secmem', 'area'],
51
+ 'lines': [
52
+ ['secmem_total', 'Total', 'absolute', None, 1024],
53
+ ['secmem_locked', 'Locked', 'absolute', None, 1024],
54
+ ['secmem_used', 'Used', 'absolute', None, 1024],
55
+ ],
56
+ },
57
+ 'network': {
58
+ 'options': [None, 'Network', 'count', 'network', 'energid.network', 'line'],
59
+ 'lines': [
60
+ ['network_connections', 'Connections', 'absolute'],
61
+ ],
62
+ },
63
+ 'timeoffset': {
64
+ 'options': [None, 'Network', 'seconds', 'network', 'energid.timeoffset', 'line'],
65
+ 'lines': [
66
+ ['network_timeoffset', 'offseet', 'absolute'],
67
+ ],
68
+ },
69
+ 'utxo': {
70
+ 'options': [None, 'UTXO', 'count', 'UTXO', 'energid.utxo', 'line'],
71
+ 'lines': [
72
+ ['utxo_count', 'UTXO', 'absolute'],
73
+ ],
74
+ },
75
+ 'xfers': {
76
+ 'options': [None, 'UTXO', 'count', 'UTXO', 'energid.xfers', 'line'],
77
+ 'lines': [
78
+ ['utxo_xfers', 'Xfers', 'absolute'],
79
+ ],
80
+ },
81
+}
82
+
83
+METHODS = {
84
+ 'getblockchaininfo': lambda r: {
85
+ 'blockchain_blocks': r['blocks'],
86
+ 'blockchain_headers': r['headers'],
87
+ 'blockchain_difficulty': r['difficulty'],
88
+ },
89
+ 'getmempoolinfo': lambda r: {
90
+ 'mempool_txcount': r['size'],
91
+ 'mempool_txsize': r['bytes'],
92
+ 'mempool_current': r['usage'],
93
+ 'mempool_max': r['maxmempool'],
94
+ },
95
+ 'getmemoryinfo': lambda r: dict([
96
+ ('secmem_' + k, v) for (k,v) in r['locked'].items()
97
+ ]),
98
+ 'getnetworkinfo': lambda r: {
99
+ 'network_timeoffset' : r['timeoffset'],
100
+ 'network_connections': r['connections'],
101
+ },
102
+ 'gettxoutsetinfo': lambda r: {
103
+ 'utxo_count' : r['txouts'],
104
+ 'utxo_xfers' : r['transactions'],
105
+ 'utxo_size' : r['disk_size'],
106
+ 'utxo_amount' : r['total_amount'],
107
+ },
108
+}
109
+
110
+JSON_RPC_VERSION = '1.1'
111
+
112
+class Service(UrlService):
113
+ def __init__(self, configuration=None, name=None):
114
+ UrlService.__init__(self, configuration=configuration, name=name)
115
+ self.order = ORDER
116
+ self.definitions = CHARTS
117
+ self.host = self.configuration.get('host', '127.0.0.1')
118
+ self.port = self.configuration.get('port', 9796)
119
+ self.url = '{scheme}://{host}:{port}'.format(
120
+ scheme=self.configuration.get('scheme', 'http'),
121
+ host=self.host,
122
+ port=self.port,
123
+ )
124
+ self.method = 'POST'
125
+ self.header = {
126
+ 'Content-Type': 'application/json',
127
+ }
128
+
129
+ def _get_data(self):
130
+ #
131
+ # Bitcoin family speak JSON-RPC version 1.0 for maximum compatibility,
132
+ # but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
133
+ # unspecified (HTTP errors and contents of 'error').
134
+ #
135
+ # 1.0 spec: https://www.jsonrpc.org/specification_v1
136
+ # 2.0 spec: https://www.jsonrpc.org/specification
137
+ #
138
+ # The call documentation: https://github.com/energicryptocurrency/core-api-documentation
139
+ #
140
+ batch = []
141
+
142
+ for i, method in enumerate(METHODS):
143
+ batch.append({
144
+ 'version': JSON_RPC_VERSION,
145
+ 'id': i,
146
+ 'method': method,
147
+ 'params': [],
148
+ })
149
+
150
+ result = self._get_raw_data(body=json.dumps(batch))
151
+
152
+ if not result:
153
+ return None
154
+
155
+ result = json.loads(result.decode('utf-8'))
156
+ data = dict()
157
+
158
+ for i, (_, handler) in enumerate(METHODS.items()):
159
+ r = result[i]
160
+ data.update(handler(r['result']))
161
+
162
+ return data
collectors/python.d.plugin/energid/energid.conf
new
+90
@@ -0,0 +1,90 @@
1
+# netdata python.d.plugin configuration for energid
2
+#
3
+# This file is in YaML format. Generally the format is:
4
+#
5
+# name: value
6
+#
7
+# There are 2 sections:
8
+# - global variables
9
+# - one or more JOBS
10
+#
11
+# JOBS allow you to collect values from multiple sources.
12
+# Each source will have its own set of charts.
13
+#
14
+# JOB parameters have to be indented (using spaces only, example below).
15
+
16
+# ----------------------------------------------------------------------
17
+# Global Variables
18
+# These variables set the defaults for all JOBs, however each JOB
19
+# may define its own, overriding the defaults.
20
+
21
+# update_every sets the default data collection frequency.
22
+# If unset, the python.d.plugin default is used.
23
+# update_every: 1
24
+
25
+# priority controls the order of charts at the netdata dashboard.
26
+# Lower numbers move the charts towards the top of the page.
27
+# If unset, the default for python.d.plugin is used.
28
+# priority: 60000
29
+
30
+# penalty indicates whether to apply penalty to update_every in case of failures.
31
+# Penalty will increase every 5 failed updates in a row. Maximum penalty is 10 minutes.
32
+# penalty: yes
33
+
34
+# autodetection_retry sets the job re-check interval in seconds.
35
+# The job is not deleted if check fails.
36
+# Attempts to start the job are made once every autodetection_retry.
37
+# This feature is disabled by default.
38
+# autodetection_retry: 0
39
+
40
+# ----------------------------------------------------------------------
41
+# JOBS (data collection sources)
42
+#
43
+# The default JOBS share the same *name*. JOBS with the same name
44
+# are mutually exclusive. Only one of them will be allowed running at
45
+# any time. This allows autodetection to try several alternatives and
46
+# pick the one that works.
47
+#
48
+# Any number of jobs is supported.
49
+#
50
+# All python.d.plugin JOBS (for all its modules) support a set of
51
+# predefined parameters. These are:
52
+#
53
+# job_name:
54
+# name: myname # the JOB's name as it will appear at the
55
+# # dashboard (by default is the job_name)
56
+# # JOBs sharing a name are mutually exclusive
57
+# update_every: 1 # the JOB's data collection frequency
58
+# priority: 60000 # the JOB's order on the dashboard
59
+# penalty: yes # the JOB's penalty
60
+# autodetection_retry: 0 # the JOB's re-check interval in seconds
61
+#
62
+# Additionally to the above, energid also supports the following:
63
+#
64
+# host: 'IP or HOSTNAME' # type <str> the RPC host to connect to
65
+# port: PORT # type <int> the RPC port to connect to
66
+# user: 'RPC username' # type <str> the RPC username to use
67
+# pass: 'RPC password' # type <str> the RPC password to use
68
+#
69
+# ----------------------------------------------------------------------
70
+# AUTO-DETECTION JOBS
71
+# only one of them will run (they have the same name)
72
+#
73
+
74
+# Defaults:
75
+# host: '127.0.0.1'
76
+# user:
77
+# pass:
78
+#
79
+
80
+# Energi mainnet
81
+energi:
82
+ port: 9796
83
+
84
+# Most likely supported Bitcoin mainnet
85
+bitcoin:
86
+ port: 8332
87
+
88
+# Most likely supported Dash mainnet
89
+dash:
90
+ port: 9998
collectors/python.d.plugin/python.d.conf
+1
@@ -41,6 +41,7 @@ chrony: no
41
# dockerd: yes
42
# dovecot: yes
43
# elasticsearch: yes
44
+# energi: yes
45
46
# this is just an example
47
example: no