1 # -*- coding: utf-8 -*-
2 # Description: prototypes for netdata python.d modules
3 # Author: Pawel Krupa (paulfantom)
8 from urllib.request import urlopen
10 from urllib2 import urlopen
13 class BaseService(object):
15 Prototype of Service class.
16 Implemented basic functionality to run jobs by `python.d.plugin`
18 def __init__(self, configuration=None, name=None):
20 This needs to be initialized in child classes
21 :param configuration: dict
25 if configuration is None:
26 self.error("BaseService: no configuration parameters supplied. Cannot create Service.")
29 self._extract_base_config(configuration)
31 self.create_timetable()
34 def _extract_base_config(self, config):
36 Get basic parameters to run service
38 config = {'update_every':1,
43 self.update_every = int(config.pop('update_every'))
44 self.priority = int(config.pop('priority'))
45 self.retries = int(config.pop('retries'))
46 self.retries_left = self.retries
47 self.configuration = config
49 def create_timetable(self, freq=None):
51 Create service timetable.
54 timetable = {'last': 1466370091.3767564,
60 freq = self.update_every
62 self.timetable = {'last': now,
63 'next': now - (now % freq) + freq,
67 def error(msg, exception=""):
69 exception = " " + str(exception).replace("\n", " ")
70 sys.stderr.write(str(msg)+exception+"\n")
78 self.error("Service " + str(self.__module__) + "doesn't implement check() function")
86 self.error("Service " + str(self.__module__) + "doesn't implement create() function?")
89 def update(self, interval):
95 self.error("Service " + str(self.__module__) + "doesn't implement update() function")
99 class UrlService(BaseService):
100 def __init__(self, configuration=None, name=None):
102 # charts definitions in format:
104 # 'chart_name_in_netdata': {
105 # 'options': "parameters defining chart (passed to CHART statement)",
107 # { 'name': 'dimension_name',
108 # 'options': 'dimension parameters (passed to DIMENSION statement)"
113 self.definitions = {}
114 # definitions are created dynamically in create() method based on 'charts' dictionary. format:
116 # 'chart_name_in_netdata' : [ charts['chart_name_in_netdata']['lines']['name'] ]
119 BaseService.__init__(self, configuration=configuration, name=name)
123 Get raw data from http request
127 f = urlopen(self.url, timeout=self.update_every)
128 raw = f.read().decode('utf-8')
130 except Exception as e:
131 self.error(self.__module__, str(e))
135 def _formatted_data(self):
137 Format data received from http request
144 Format configuration data and try to connect to server
147 if self.name is None:
150 self.name = str(self.name)
152 self.url = str(self.configuration['url'])
153 except (KeyError, TypeError):
156 if self._formatted_data() is not None:
166 for name in self.order:
167 if name not in self.charts:
169 self.definitions[name] = []
170 for line in self.charts[name]['lines']:
171 self.definitions[name].append(line['name'])
174 data = self._formatted_data()
177 for name in self.order:
178 header = "CHART " + \
179 self.__module__ + "_" + \
182 self.charts[name]['options'] + " " + \
183 str(self.priority + idx) + " " + \
184 str(self.update_every)
186 # check if server has this datapoint
187 for line in self.charts[name]['lines']:
188 if line['name'] in data:
189 content += "DIMENSION " + line['name'] + " " + line['options'] + "\n"
200 def update(self, interval):
206 data = self._formatted_data()
210 for chart, dimensions in self.definitions.items():
211 header = "BEGIN " + self.__module__ + "_" + str(self.name) + "." + chart + " " + str(interval)
213 for dim in dimensions:
215 c += "\nSET " + dim + " = " + str(data[dim])