-
Notifications
You must be signed in to change notification settings - Fork 1
/
zfx_collectors.py
108 lines (95 loc) · 2.81 KB
/
zfx_collectors.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
import os
import re
from prometheus_client.core import GaugeMetricFamily
class StatsCollector(object):
"""
Generic ZFS statistic collector.
"""
def __init__(self, path, m_pfx, m_desc):
"""
Initialized the collector object.
Parameters
----------
path : str
The full path to the metric file.
m_pfx : str
Prefix for the names of generated metrics.
m_desc : str
Metric description string that will be set for every metric from the file.
"""
self.path = path
self.m_pfx = m_pfx
self.m_desc = m_desc
def collect(self):
"""
Collects metrics from the stats file. The expected syntax of the lines
with metric data has 3 columns, ie.:
hits 4 168948958
misses 4 4767869
...
Returns
-------
Yields metrics of the Gauge type.
"""
try:
with open(self.path, 'r') as f:
mline = re.compile('^[_a-z]+ +[0-9] +[0-9]+$')
for l in f:
if not mline.match(l):
continue
items = re.split(r' +', l)
if len(items) != 3 and type(items[1]) == int:
continue
yield GaugeMetricFamily(self.m_pfx + items[0], self.m_desc, value=float(items[2]))
except Exception as e:
print('Error: {}'.format(str(e)))
class PoolstatsCollector(object):
"""
Per pool statistic collector.
"""
def __init__(self):
self.states = { # valid pool states
'ONLINE': 1.0,
'DEGRADED': 0.2,
'FAULTED': 0.1,
'OFFLINE': 0.0,
'UNAVAIL': -1.0,
'REMOVED': -2.0
}
def get_state_num(self, state):
"""
Translates the state string into the corresponding float number
or returns -3.0 if not found.
"""
return self.states[state] if state in self.states.keys() else -3.0 # UNKNOWN
def collect(self):
"""
Discovers the pools by searching for folders in /proc/spl/kstat/zfs,
then extracts the state and IO stats from the files.
Returns
-------
Yields metrics of the Gauge type.
"""
# Metric declarations
# Find the ZFS pools
for pooldir in [f.path for f in os.scandir('/proc/spl/kstat/zfs') if f.is_dir()]:
poolname = pooldir.split('/')[-1]
# Load state from file
try:
with open(pooldir + '/state', 'r') as f:
for l in f:
STATE = GaugeMetricFamily('zfs_pool_state', 'Pool state (ONLINE = 1, OFFLINE = 0)', labels=['pool'])
STATE.add_metric([poolname], self.get_state_num(l.strip()))
yield STATE
except Exception as e:
print('Error: {}'.format(str(e)))
# Load IO stats from file
iostats_p = pooldir + '/io'
lines = open(iostats_p, 'r').readlines() if os.path.isfile(iostats_p) else []
if len(lines) > 2:
keys = re.split(r' +', lines[1].strip())
vals = re.split(r' +', lines[2].strip())
for (key, value) in zip(keys, vals):
IOSTATS = GaugeMetricFamily('zfs_pool_io_' + key, 'Pool IO statistics', labels=['pool'])
IOSTATS.add_metric([poolname], value)
yield IOSTATS