@cryptotaxi247 / netdata-1 / commits / 651ae55ff

litespeed python module added

lgz committed Jun 4, 2018 at 14:47 UTC 651ae55ff0352e662347906b688ca7a6c602af15
1 file changed +122
python.d/litespeed.chart.py new
+122
@@ -0,0 +1,122 @@
1 +# -*- coding: utf-8 -*-
2 +# Description: litespeed netdata python.d module
3 +# Author: Ilya Maschenko (l2isbad)
4 +
5 +import glob
6 +import re
7 +import os
8 +
9 +from bases.FrameworkServices.SimpleService import SimpleService
10 +
11 +# charts order (can be overridden if you want less charts, or different order)
12 +ORDER = ['requests', 'pub_cache_hits', 'priv_cache_hits', 'static_hits']
13 +
14 +CHARTS = {
15 + 'requests': {
16 + 'options': [None, 'Requests', 'req/sec', 'requests', 'litespeed.requests', 'line'],
17 + 'lines': [
18 + ["requests", None, "incremental", 1, 100]
19 + ]},
20 + 'pub_cache_hits': {
21 + 'options': [None, 'Public Cache Hits', 'hits/sec', 'cache', 'litespeed.pub_cache', 'line'],
22 + 'lines': [
23 + ["pub_cache_hits", "hits", "incremental", 1, 100]
24 + ]},
25 + 'priv_cache_hits': {
26 + 'options': [None, 'Private Cache Hits', 'hits/sec', 'cache', 'litespeed.priv_cache', 'line'],
27 + 'lines': [
28 + ["priv_cache_hits", "hits", "incremental", 1, 100]
29 + ]},
30 + 'static_hits': {
31 + 'options': [None, 'Static Hits', 'hits/sec', 'static', 'litespeed.static', 'line'],
32 + 'lines': [
33 + ["static_hits", "hits", "incremental", 1, 100]
34 + ]},
35 +}
36 +
37 +KEYS = [
38 + ('TOT_REQS', 'requests'),
39 + ('TOTAL_PUB_CACHE_HITS', 'pub_cache_hits'),
40 + ('TOTAL_PRIVATE_CACHE_HITS', 'priv_cache_hits'),
41 + ('TOTAL_STATIC_HITS', 'static_hits'),
42 +]
43 +
44 +RE = re.compile(r'([A-Z_]+): ([0-9.]+)')
45 +
46 +
47 +class DataFile:
48 + def __init__(self, abs_path):
49 + self.path = abs_path
50 + self.mtime = os.stat(abs_path).st_mtime
51 +
52 + def is_changed(self):
53 + o = self.mtime
54 + n = os.stat(self.path).st_mtime
55 + self.mtime = n
56 + return o != n
57 +
58 +
59 +class Service(SimpleService):
60 + def __init__(self, configuration=None, name=None):
61 + SimpleService.__init__(self, configuration=configuration, name=name)
62 + self.order = ORDER
63 + self.definitions = CHARTS
64 + self.path = self.configuration.get('path')
65 + self.files = list()
66 + self.data = {
67 + "requests": 0,
68 + "pub_cache_hits": 0,
69 + "priv_cache_hits": 0,
70 + "static_hits": 0,
71 + }
72 +
73 + def check(self):
74 + if not self.path:
75 + self.error('"path" not specified')
76 + return False
77 +
78 + fs = glob.glob(os.path.join(self.path, ".rtreport*"))
79 +
80 + if not fs:
81 + self.error('"{0}" has no "rtreport" files or dir is not readable'.format(self.path))
82 + return None
83 +
84 + for f in fs:
85 + if not is_readable_file(f):
86 + self.error("{0} is not readable".format(f))
87 + continue
88 + self.files.append(DataFile(f))
89 +
90 + return bool(self.files)
91 +
92 + def get_data(self):
93 + """
94 + Format data received from http request
95 + :return: dict
96 + """
97 + for f in self.files:
98 + try:
99 + if not f.is_changed():
100 + continue
101 + with open(f.path) as b:
102 + lines = b.readlines()
103 + except (OSError, IOError) as err:
104 + self.error(err)
105 + return None
106 + else:
107 + self.parse_file(lines)
108 +
109 + return self.data
110 +
111 + def parse_file(self, lines):
112 + for line in lines:
113 + if not line.startswith("REQ_RATE []"):
114 + continue
115 + m = dict(RE.findall(line))
116 + for k, d in KEYS:
117 + self.data[d] = float(m[k]) * 100 if k in m else 0
118 + break
119 +
120 +
121 +def is_readable_file(v):
122 + return os.path.isfile(v) and os.access(v, os.R_OK)