energid.chart.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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. import json
  10. from bases.FrameworkServices.UrlService import UrlService
  11. update_every = 5
  12. ORDER = [
  13. 'blockindex',
  14. 'difficulty',
  15. 'mempool',
  16. 'secmem',
  17. 'network',
  18. 'timeoffset',
  19. 'utxo',
  20. 'xfers',
  21. ]
  22. CHARTS = {
  23. 'blockindex': {
  24. 'options': [None, 'Blockchain Index', 'count', 'blockchain', 'energi.blockindex', 'area'],
  25. 'lines': [
  26. ['blockchain_blocks', 'blocks', 'absolute'],
  27. ['blockchain_headers', 'headers', 'absolute'],
  28. ]
  29. },
  30. 'difficulty': {
  31. 'options': [None, 'Blockchain Difficulty', 'difficulty', 'blockchain', 'energi.difficulty', 'line'],
  32. 'lines': [
  33. ['blockchain_difficulty', 'Diff', 'absolute'],
  34. ],
  35. },
  36. 'mempool': {
  37. 'options': [None, 'MemPool', 'MiB', 'memory', 'energid.mempool', 'area'],
  38. 'lines': [
  39. ['mempool_max', 'Max', 'absolute', None, 1024 * 1024],
  40. ['mempool_current', 'Usage', 'absolute', None, 1024 * 1024],
  41. ['mempool_txsize', 'TX Size', 'absolute', None, 1024 * 1024],
  42. ],
  43. },
  44. 'secmem': {
  45. 'options': [None, 'Secure Memory', 'KiB', 'memory', 'energid.secmem', 'area'],
  46. 'lines': [
  47. ['secmem_total', 'Total', 'absolute', None, 1024],
  48. ['secmem_locked', 'Locked', 'absolute', None, 1024],
  49. ['secmem_used', 'Used', 'absolute', None, 1024],
  50. ],
  51. },
  52. 'network': {
  53. 'options': [None, 'Network', 'count', 'network', 'energid.network', 'line'],
  54. 'lines': [
  55. ['network_connections', 'Connections', 'absolute'],
  56. ],
  57. },
  58. 'timeoffset': {
  59. 'options': [None, 'Network', 'seconds', 'network', 'energid.timeoffset', 'line'],
  60. 'lines': [
  61. ['network_timeoffset', 'offseet', 'absolute'],
  62. ],
  63. },
  64. 'utxo': {
  65. 'options': [None, 'UTXO', 'count', 'UTXO', 'energid.utxo', 'line'],
  66. 'lines': [
  67. ['utxo_count', 'UTXO', 'absolute'],
  68. ],
  69. },
  70. 'xfers': {
  71. 'options': [None, 'UTXO', 'count', 'UTXO', 'energid.xfers', 'line'],
  72. 'lines': [
  73. ['utxo_xfers', 'Xfers', 'absolute'],
  74. ],
  75. },
  76. }
  77. METHODS = {
  78. 'getblockchaininfo': lambda r: {
  79. 'blockchain_blocks': r['blocks'],
  80. 'blockchain_headers': r['headers'],
  81. 'blockchain_difficulty': r['difficulty'],
  82. },
  83. 'getmempoolinfo': lambda r: {
  84. 'mempool_txcount': r['size'],
  85. 'mempool_txsize': r['bytes'],
  86. 'mempool_current': r['usage'],
  87. 'mempool_max': r['maxmempool'],
  88. },
  89. 'getmemoryinfo': lambda r: dict([
  90. ('secmem_' + k, v) for (k, v) in r['locked'].items()
  91. ]),
  92. 'getnetworkinfo': lambda r: {
  93. 'network_timeoffset': r['timeoffset'],
  94. 'network_connections': r['connections'],
  95. },
  96. 'gettxoutsetinfo': lambda r: {
  97. 'utxo_count': r['txouts'],
  98. 'utxo_xfers': r['transactions'],
  99. 'utxo_size': r['disk_size'],
  100. 'utxo_amount': r['total_amount'],
  101. },
  102. }
  103. JSON_RPC_VERSION = '1.1'
  104. class Service(UrlService):
  105. def __init__(self, configuration=None, name=None):
  106. UrlService.__init__(self, configuration=configuration, name=name)
  107. self.order = ORDER
  108. self.definitions = CHARTS
  109. self.host = self.configuration.get('host', '127.0.0.1')
  110. self.port = self.configuration.get('port', 9796)
  111. self.url = '{scheme}://{host}:{port}'.format(
  112. scheme=self.configuration.get('scheme', 'http'),
  113. host=self.host,
  114. port=self.port,
  115. )
  116. self.method = 'POST'
  117. self.header = {
  118. 'Content-Type': 'application/json',
  119. }
  120. def _get_data(self):
  121. #
  122. # Bitcoin family speak JSON-RPC version 1.0 for maximum compatibility,
  123. # but uses JSON-RPC 1.1/2.0 standards for parts of the 1.0 standard that were
  124. # unspecified (HTTP errors and contents of 'error').
  125. #
  126. # 1.0 spec: https://www.jsonrpc.org/specification_v1
  127. # 2.0 spec: https://www.jsonrpc.org/specification
  128. #
  129. # The call documentation: https://github.com/energicryptocurrency/core-api-documentation
  130. #
  131. batch = []
  132. for i, method in enumerate(METHODS):
  133. batch.append({
  134. 'version': JSON_RPC_VERSION,
  135. 'id': i,
  136. 'method': method,
  137. 'params': [],
  138. })
  139. result = self._get_raw_data(body=json.dumps(batch))
  140. if not result:
  141. return None
  142. result = json.loads(result.decode('utf-8'))
  143. data = dict()
  144. for i, (_, handler) in enumerate(METHODS.items()):
  145. r = result[i]
  146. data.update(handler(r['result']))
  147. return data