-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcollectd_readfiles_python.py
executable file
·141 lines (127 loc) · 5.34 KB
/
collectd_readfiles_python.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env python
#
# collectd-readfiles-python
# ======================
#
# Plugin for collectd that reads metrics from file(s) specified
# in the Module section for the Plugin in collectd.conf
# Each file is assumed to contain a metric value on the first line.
# Metrics are submitted to all enabled write plugins.
#
# https://github.com/mwtzzz/collectd-readfiles/
#
import sys
import string
import os
import collectd
import threading
class ObtainMetrics(object):
def __init__(self):
self.plugin_name = 'collectd-readfiles-python'
self.derivemetricfiles = ""
self.gaugemetricfiles = ""
self.interval = 60.0
self.verbose_logging = True
"""
Whether or not collectd.[info|warning|etc] messages get written depends
on LogLevel for syslog in /etc/collectd.conf
"""
def log_verbose(self, msg):
if not self.verbose_logging:
return
collectd.warning('%s plugin [verbose]: %s' % (self.plugin_name, msg))
def configure_callback(self, conf):
"""
Grab the configuration.
"""
for node in conf.children:
# self.log_verbose("node.values: %s\n" % str(node.values))
val = str(node.values[0])
if node.key == 'DeriveMetricFiles':
self.derivemetricfiles = node.values
elif node.key == 'GaugeMetricFiles':
self.gaugemetricfiles = node.values
elif node.key == 'Interval':
self.interval = float(val)
elif node.key == 'PluginName':
self.plugin_name = val
elif node.key == 'Verbose':
self.verbose_logging = val in ['True', 'true']
else:
collectd.warning(
'%s plugin: Unknown config key: %s.' % (
self.plugin_name,
node.key))
self.log_verbose(
'Configured with DeriveMetricFiles %s, GaugeMetricFiles %s, Interval %s, Plugin Name %s' % (
self.derivemetricfiles, self.gaugemetricfiles, self.interval, self.plugin_name))
collectd.register_read(self.read_callback, self.interval)
# collectd runs the read callback in a separate thread at frequency of self.interval
def read_callback(self):
def read_and_dispatch_file(datasource, F_type):
try:
metricfile = open(datasource, 'r')
except:
collectd.warning("Unable to open %s. Moving on to next file ...\n" % datasource)
return
self.log_verbose("Obtaining metric for file: %s\n" % datasource)
val = collectd.Values()
inst = os.path.basename(os.path.dirname(datasource))
if not inst:
inst = os.path.basename(datasource)
# the following four components determine the metric name
val.plugin = self.plugin_name
val.plugin_instance = inst
val.type = F_type
val.type_instance = os.path.basename(datasource)
#
metricvalue = metricfile.readline()
if not metricvalue:
collectd.warning("Unable to read a value from %s. Moving on to next file ... \n" % datasource)
metricfile.close()
return
val.values = [float(metricvalue)]
val.meta={'0': True}
self.log_verbose("Dispatching value %s with interval %s\n" % (val.values, self.interval))
"""
Dispatch values stored in the val object to all enabled write plugins.
Interval is basically unused and/or expected to be the same as
how often the callback is called.
"""
val.dispatch(interval=self.interval)
metricfile.close()
"""
Metric types can be derive, counter, gauge, or absolute.
See https://docs.opnfv.org/en/stable-fraser/submodules/barometer/docs/development/requirements/02-collectd.html
and see man 5 types.db
"""
for file in self.derivemetricfiles:
self.log_verbose("Processing %s\n" % file)
"""
Note: using multiprocessing instead of threading results in nothing
getting written
"""
p = threading.Thread(target=read_and_dispatch_file,
args=(file,"derive"))
p.start()
for file in self.gaugemetricfiles:
self.log_verbose("Processing %s\n" % file)
p = threading.Thread(target=read_and_dispatch_file,
args=(file,"gauge"))
p.start()
def restore_sigchld():
"""
See https://github.com/deniszh/collectd-iostat-python/issues/2
"""
if sys.version_info[0] == 2 and sys.version_info[1] <= 6:
signal.signal(signal.SIGCHLD, signal.SIG_DFL)
# if this script is launched from command line just print to standard out
if __name__ == '__main__':
print("%s lauched directly from command line" % (sys.argv[0]))
sys.exit(0)
# otherwise if it is launched from within collectd then do the collectd stuff
else:
stuff = ObtainMetrics()
collectd.register_init(restore_sigchld)
collectd.register_config(stuff.configure_callback)
collectd.warning("This plugin has exited.")