rethinkdbs.chart.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. # -*- coding: utf-8 -*-
  2. # Description: rethinkdb netdata python.d module
  3. # Author: Ilya Mashchenko (ilyam8)
  4. # SPDX-License-Identifier: GPL-3.0-or-later
  5. try:
  6. import rethinkdb as rdb
  7. HAS_RETHINKDB = True
  8. except ImportError:
  9. HAS_RETHINKDB = False
  10. from bases.FrameworkServices.SimpleService import SimpleService
  11. ORDER = [
  12. 'cluster_connected_servers',
  13. 'cluster_clients_active',
  14. 'cluster_queries',
  15. 'cluster_documents',
  16. ]
  17. def cluster_charts():
  18. return {
  19. 'cluster_connected_servers': {
  20. 'options': [None, 'Connected Servers', 'servers', 'cluster', 'rethinkdb.cluster_connected_servers',
  21. 'stacked'],
  22. 'lines': [
  23. ['cluster_servers_connected', 'connected'],
  24. ['cluster_servers_missing', 'missing'],
  25. ]
  26. },
  27. 'cluster_clients_active': {
  28. 'options': [None, 'Active Clients', 'clients', 'cluster', 'rethinkdb.cluster_clients_active',
  29. 'line'],
  30. 'lines': [
  31. ['cluster_clients_active', 'active'],
  32. ]
  33. },
  34. 'cluster_queries': {
  35. 'options': [None, 'Queries', 'queries/s', 'cluster', 'rethinkdb.cluster_queries', 'line'],
  36. 'lines': [
  37. ['cluster_queries_per_sec', 'queries'],
  38. ]
  39. },
  40. 'cluster_documents': {
  41. 'options': [None, 'Documents', 'documents/s', 'cluster', 'rethinkdb.cluster_documents', 'line'],
  42. 'lines': [
  43. ['cluster_read_docs_per_sec', 'reads'],
  44. ['cluster_written_docs_per_sec', 'writes'],
  45. ]
  46. },
  47. }
  48. def server_charts(n):
  49. o = [
  50. '{0}_client_connections'.format(n),
  51. '{0}_clients_active'.format(n),
  52. '{0}_queries'.format(n),
  53. '{0}_documents'.format(n),
  54. ]
  55. f = 'server {0}'.format(n)
  56. c = {
  57. o[0]: {
  58. 'options': [None, 'Client Connections', 'connections', f, 'rethinkdb.client_connections', 'line'],
  59. 'lines': [
  60. ['{0}_client_connections'.format(n), 'connections'],
  61. ]
  62. },
  63. o[1]: {
  64. 'options': [None, 'Active Clients', 'clients', f, 'rethinkdb.clients_active', 'line'],
  65. 'lines': [
  66. ['{0}_clients_active'.format(n), 'active'],
  67. ]
  68. },
  69. o[2]: {
  70. 'options': [None, 'Queries', 'queries/s', f, 'rethinkdb.queries', 'line'],
  71. 'lines': [
  72. ['{0}_queries_total'.format(n), 'queries', 'incremental'],
  73. ]
  74. },
  75. o[3]: {
  76. 'options': [None, 'Documents', 'documents/s', f, 'rethinkdb.documents', 'line'],
  77. 'lines': [
  78. ['{0}_read_docs_total'.format(n), 'reads', 'incremental'],
  79. ['{0}_written_docs_total'.format(n), 'writes', 'incremental'],
  80. ]
  81. },
  82. }
  83. return o, c
  84. class Cluster:
  85. def __init__(self, raw):
  86. self.raw = raw
  87. def data(self):
  88. qe = self.raw['query_engine']
  89. return {
  90. 'cluster_clients_active': qe['clients_active'],
  91. 'cluster_queries_per_sec': qe['queries_per_sec'],
  92. 'cluster_read_docs_per_sec': qe['read_docs_per_sec'],
  93. 'cluster_written_docs_per_sec': qe['written_docs_per_sec'],
  94. 'cluster_servers_connected': 0,
  95. 'cluster_servers_missing': 0,
  96. }
  97. class Server:
  98. def __init__(self, raw):
  99. self.name = raw['server']
  100. self.raw = raw
  101. def error(self):
  102. return self.raw.get('error')
  103. def data(self):
  104. qe = self.raw['query_engine']
  105. d = {
  106. 'client_connections': qe['client_connections'],
  107. 'clients_active': qe['clients_active'],
  108. 'queries_total': qe['queries_total'],
  109. 'read_docs_total': qe['read_docs_total'],
  110. 'written_docs_total': qe['written_docs_total'],
  111. }
  112. return dict(('{0}_{1}'.format(self.name, k), d[k]) for k in d)
  113. # https://pypi.org/project/rethinkdb/2.4.0/
  114. # rdb.RethinkDB() can be used as rdb drop in replacement.
  115. # https://github.com/rethinkdb/rethinkdb-python#quickstart
  116. def get_rethinkdb():
  117. if hasattr(rdb, 'RethinkDB'):
  118. return rdb.RethinkDB()
  119. return rdb
  120. class Service(SimpleService):
  121. def __init__(self, configuration=None, name=None):
  122. SimpleService.__init__(self, configuration=configuration, name=name)
  123. self.order = list(ORDER)
  124. self.definitions = cluster_charts()
  125. self.host = self.configuration.get('host', '127.0.0.1')
  126. self.port = self.configuration.get('port', 28015)
  127. self.user = self.configuration.get('user', 'admin')
  128. self.password = self.configuration.get('password')
  129. self.timeout = self.configuration.get('timeout', 2)
  130. self.rdb = None
  131. self.conn = None
  132. self.alive = True
  133. def check(self):
  134. if not HAS_RETHINKDB:
  135. self.error('"rethinkdb" module is needed to use rethinkdbs.py')
  136. return False
  137. self.debug("rethinkdb driver version {0}".format(rdb.__version__))
  138. self.rdb = get_rethinkdb()
  139. if not self.connect():
  140. return None
  141. stats = self.get_stats()
  142. if not stats:
  143. return None
  144. for v in stats[1:]:
  145. if get_id(v) == 'server':
  146. o, c = server_charts(v['server'])
  147. self.order.extend(o)
  148. self.definitions.update(c)
  149. return True
  150. def get_data(self):
  151. if not self.is_alive():
  152. return None
  153. stats = self.get_stats()
  154. if not stats:
  155. return None
  156. data = dict()
  157. # cluster
  158. data.update(Cluster(stats[0]).data())
  159. # servers
  160. for v in stats[1:]:
  161. if get_id(v) != 'server':
  162. continue
  163. s = Server(v)
  164. if s.error():
  165. data['cluster_servers_missing'] += 1
  166. else:
  167. data['cluster_servers_connected'] += 1
  168. data.update(s.data())
  169. return data
  170. def get_stats(self):
  171. try:
  172. return list(self.rdb.db('rethinkdb').table('stats').run(self.conn).items)
  173. except rdb.errors.ReqlError:
  174. self.alive = False
  175. return None
  176. def connect(self):
  177. try:
  178. self.conn = self.rdb.connect(
  179. host=self.host,
  180. port=self.port,
  181. user=self.user,
  182. password=self.password,
  183. timeout=self.timeout,
  184. )
  185. self.alive = True
  186. return True
  187. except rdb.errors.ReqlError as error:
  188. self.error('Connection to {0}:{1} failed: {2}'.format(self.host, self.port, error))
  189. return False
  190. def reconnect(self):
  191. # The connection is already closed after rdb.errors.ReqlError,
  192. # so we do not need to call conn.close()
  193. if self.connect():
  194. return True
  195. return False
  196. def is_alive(self):
  197. if not self.alive:
  198. return self.reconnect()
  199. return True
  200. def get_id(v):
  201. return v['id'][0]