beanstalk module initial version
lgz committed
Nov 3, 2017 at 00:23 UTC
236d3a1651bb88c9e932433fcd1b42561eb7cb53
1 file changed
+162
python.d/beanstalk.chart.py
new
+162
@@ -0,0 +1,162 @@
1
+# -*- coding: utf-8 -*-
2
+# Description: beanstalk netdata python.d module
3
+# Author: l2isbad
4
+
5
+from collections import defaultdict
6
+from sys import version_info
7
+
8
+try:
9
+ import beanstalkc
10
+ BEANSTALKC = True
11
+except ImportError:
12
+ BEANSTALKC = False
13
+
14
+
15
+if version_info[:2] > (3, 1):
16
+ import pyyaml3 as yaml
17
+else:
18
+ import pyyaml2 as yaml
19
+
20
+
21
+from bases.FrameworkServices.SimpleService import SimpleService
22
+
23
+# default module values (can be overridden per job in `config`)
24
+# update_every = 2
25
+priority = 60000
26
+retries = 60
27
+
28
+
29
+def chart_template(name):
30
+ order = ['{0}_jobs_rate'.format(name),
31
+ '{0}_jobs'.format(name),
32
+ '{0}_connections'.format(name),
33
+ '{0}_commands'.format(name),
34
+ '{0}_pause'.format(name)
35
+ ]
36
+ family = 'tube {0}'.format(name)
37
+
38
+ charts = {
39
+ order[0]: {
40
+ 'options': [None, 'Job Rate', 'jobs/s', family, 'beanstalk.jobs_rate', 'area'],
41
+ 'lines': [
42
+ ['_'.join([name, 'total-jobs']), 'jobs', 'incremental']
43
+ ]},
44
+ order[1]: {
45
+ 'options': [None, 'Jobs', 'jobs', family, 'beanstalk.jobs', 'stacked'],
46
+ 'lines': [
47
+ ['_'.join([name, 'current-jobs-urgent']), 'urgent'],
48
+ ['_'.join([name, 'current-jobs-ready']), 'ready'],
49
+ ['_'.join([name, 'current-jobs-reserved']), 'reserved'],
50
+ ['_'.join([name, 'current-jobs-delayed']), 'delayed'],
51
+ ['_'.join([name, 'current-jobs-buried']), 'buried']
52
+ ]},
53
+ order[2]: {
54
+ 'options': [None, 'Connections', 'connections', family, 'beanstalk.connections', 'stacked'],
55
+ 'lines': [
56
+ ['_'.join([name, 'current-using']), 'using'],
57
+ ['_'.join([name, 'current-waiting']), 'waiting'],
58
+ ['_'.join([name, 'current-watching']), 'watching']
59
+ ]},
60
+ order[3]: {
61
+ 'options': [None, 'Commands', 'command/s', family, 'beanstalk.commands', 'stacked'],
62
+ 'lines': [
63
+ ['_'.join([name, 'cmd-delete']), 'deletes', 'incremental'],
64
+ ['_'.join([name, 'cmd-pause-tube']), 'pauses', 'incremental']
65
+ ]},
66
+ order[4]: {
67
+ 'options': [None, 'Pause', 'seconds', family, 'beanstalk.pause', 'stacked'],
68
+ 'lines': [
69
+ ['_'.join([name, 'pause']), 'since'],
70
+ ['_'.join([name, 'pause-time-left']), 'left']
71
+ ]}
72
+
73
+ }
74
+
75
+ return order, charts
76
+
77
+
78
+class Service(SimpleService):
79
+ def __init__(self, configuration=None, name=None):
80
+ SimpleService.__init__(self, configuration=configuration, name=name)
81
+ self.configuration = configuration
82
+ self.conn = self.connect()
83
+ self.order = list()
84
+ self.definitions = dict()
85
+ self.alive = True
86
+
87
+ def check(self):
88
+ if not BEANSTALKC:
89
+ self.error("'beanstalkc' module is needed to use beanstalk.chart.py")
90
+ return False
91
+
92
+ if not self.conn:
93
+ return False
94
+
95
+ for tube in self.conn.tubes():
96
+ order, charts = chart_template(tube)
97
+ self.order.extend(order)
98
+ self.definitions.update(charts)
99
+
100
+ return bool(self.order)
101
+
102
+ def get_data(self):
103
+ """
104
+ Format data received from shell command
105
+ :return: dict
106
+ """
107
+ if not self.is_alive():
108
+ return None
109
+ else:
110
+ self.alive = True
111
+
112
+ tubes_stats, data = defaultdict(dict), dict()
113
+ try:
114
+ for tube in self.conn.tubes():
115
+ stats = self.conn.stats_tube(tube)
116
+ for stat in stats:
117
+ dimension, value = '_'.join([tube, stat]), stats[stat]
118
+ tubes_stats[tube][dimension] = value
119
+ except beanstalkc.SocketError:
120
+ self.alive = False
121
+ return None
122
+
123
+ for tube in tubes_stats:
124
+ if tube + '_jobs' not in self.charts.active_charts():
125
+ self.create_new_tube_charts(tube)
126
+
127
+ data.update(tubes_stats[tube])
128
+
129
+ return data or None
130
+
131
+ def create_new_tube_charts(self, tube):
132
+ order, charts = chart_template(tube)
133
+
134
+ for chart_name in order:
135
+ params = [chart_name] + charts[chart_name]['options']
136
+ dimensions = charts[chart_name]['lines']
137
+
138
+ new_chart = self.charts.add_chart(params)
139
+ for dimension in dimensions:
140
+ new_chart.add_dimension(dimension)
141
+
142
+ def connect(self):
143
+ host = self.configuration.get('host', '127.0.0.1')
144
+ port = self.configuration.get('port', 11300)
145
+ try:
146
+ return beanstalkc.Connection(host=host,
147
+ port=port)
148
+ except beanstalkc.SocketError as error:
149
+ self.error('Connection to {0}:{1} failed: {2}'.format(host, port, error))
150
+ return None
151
+
152
+ def reconnect(self):
153
+ try:
154
+ self.conn.reconnect()
155
+ return True
156
+ except beanstalkc.SocketError:
157
+ return False
158
+
159
+ def is_alive(self):
160
+ if not self.alive:
161
+ return self.reconnect()
162
+ return True