Skip to content

Commit dc2716b

Browse files
munin: metadata usage warning and critical levels
1 parent 4aa37fc commit dc2716b

1 file changed

Lines changed: 76 additions & 37 deletions

File tree

examples/munin/plugins/btrfs_usage

Lines changed: 76 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,55 @@
2121
import btrfs
2222
import os
2323
import sys
24+
from math import floor
25+
26+
def calculate_munin_values(fs):
27+
# Get detailed usage statistics.
28+
usage = fs.usage()
29+
30+
# Whatever happens, we should not stack the graph above this. IOW, the
31+
# unallocated bytes we end up with is just whatever is left over after
32+
# doing all other things.
33+
left = usage.total
34+
35+
if not fs.mixed_groups():
36+
data_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_DATA].used
37+
data_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_DATA].allocated
38+
metadata_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_METADATA].used
39+
metadata_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_METADATA].allocated
40+
left = left - data_allocated - metadata_allocated
41+
usage_info = {
42+
'data_used': data_used,
43+
'data_allocated': data_allocated,
44+
'data_unused': data_allocated - data_used,
45+
'metadata_used': metadata_used,
46+
'metadata_allocated': metadata_allocated,
47+
'metadata_unused': metadata_allocated - metadata_used,
48+
}
49+
else:
50+
mixed_type = btrfs.BLOCK_GROUP_DATA | btrfs.BLOCK_GROUP_METADATA
51+
used = usage.block_group_type_usage[mixed_type].used
52+
allocated = usage.block_group_type_usage[mixed_type].allocated
53+
left -= allocated
54+
usage_info = {
55+
'data_metadata_used': used,
56+
'data_metadata_unused': allocated-used,
57+
}
58+
system_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_SYSTEM].used
59+
usage_info['system_used'] = system_used
60+
system_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_SYSTEM].allocated
61+
usage_info['system_unused'] = system_allocated - system_used
62+
left -= system_allocated
63+
64+
usage_info['parity'] = usage.parity
65+
left -= usage.parity
66+
usage_info['non_alloc_reclaimable'] = usage.unallocatable_reclaimable
67+
left -= usage.unallocatable_reclaimable
68+
usage_info['non_alloc'] = usage.unallocatable_hard
69+
usage_info['unallocated'] = max(left - usage.unallocatable_hard, 0)
70+
usage_info['total'] = usage.total
71+
72+
return usage_info
2473

2574

2675
def munin_config(fs):
@@ -48,6 +97,14 @@ def munin_config(fs):
4897
print("metadata_unused.draw STACK")
4998
print("metadata_unused.info Unused Metadata")
5099
print("metadata_unused.colour 0000CC")
100+
101+
usage_info = calculate_munin_values(fs)
102+
#Assuming metadata is allocated by 256MB chunks
103+
available_unallocated_for_metadata = floor(usage_info['unallocated'] / (2**28)) * (2**28)
104+
metadata_warning = int((usage_info['metadata_allocated'] * 0.15) - available_unallocated_for_metadata)
105+
metadata_critical = int((usage_info['metadata_allocated'] * 0.10) - available_unallocated_for_metadata)
106+
print("metadata_unused.warning {}:".format(metadata_warning))
107+
print("metadata_unused.critical {}:".format(metadata_critical))
51108
else:
52109
print("data_metadata_used.label Used Data+Metadata")
53110
print("data_metadata_used.draw AREA")
@@ -94,46 +151,28 @@ def munin_config(fs):
94151
def munin_values(fs):
95152
print("multigraph btrfs_usage_{0}".format(str(fs.fsid).replace('-', '_')))
96153

97-
# Get detailed usage statistics.
98-
usage = fs.usage()
99-
100-
# Whatever happens, we should not stack the graph above this. IOW, the
101-
# unallocated bytes we end up with is just whatever is left over after
102-
# doing all other things.
103-
left = usage.total
154+
usage_info = calculate_munin_values(fs)
104155

105156
if not fs.mixed_groups():
106-
data_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_DATA].used
107-
data_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_DATA].allocated
108-
metadata_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_METADATA].used
109-
metadata_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_METADATA].allocated
110-
print("data_used.value {}".format(data_used))
111-
print("data_unused.value {}".format(data_allocated - data_used))
112-
print("metadata_used.value {}".format(metadata_used))
113-
print("metadata_unused.value {}".format(metadata_allocated - metadata_used))
114-
left = left - data_allocated - metadata_allocated
157+
template = (
158+
"data_used.value {data_used}\n"
159+
"data_unused.value {data_unused}\n"
160+
"metadata_used.value {metadata_used}\n"
161+
"metadata_unused.value {metadata_unused}\n")
115162
else:
116-
mixed_type = btrfs.BLOCK_GROUP_DATA | btrfs.BLOCK_GROUP_METADATA
117-
used = usage.block_group_type_usage[mixed_type].used
118-
allocated = usage.block_group_type_usage[mixed_type].allocated
119-
print("data_metadata_used.value {}".format(used))
120-
print("data_metadata_unused.value {}".format(allocated - used))
121-
left -= allocated
122-
system_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_SYSTEM].used
123-
system_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_SYSTEM].allocated
124-
print("system_used.value {}".format(system_used))
125-
print("system_unused.value {}".format(system_allocated - system_used))
126-
left -= system_allocated
127-
128-
print("parity.value {}".format(usage.parity))
129-
left -= usage.parity
130-
print("non_alloc_reclaimable.value {}".format(usage.unallocatable_reclaimable))
131-
left -= usage.unallocatable_reclaimable
132-
print("non_alloc.value {}".format(usage.unallocatable_hard))
133-
left = max(left - usage.unallocatable_hard, 0)
134-
print("unallocated.value {}".format(left))
135-
print("total.value {}".format(usage.total))
136-
print("")
163+
template = (
164+
"data_metadata_used.value {data_metadata_used}\n"
165+
"data_metadata_unused.value {data_metadata_unused}\n")
166+
167+
template += (
168+
"system_used.value {system_used}\n"
169+
"system_unused.value {system_unused}\n"
170+
"parity.value {parity}\n"
171+
"non_alloc_reclaimable.value {non_alloc_reclaimable}\n"
172+
"non_alloc.value {non_alloc}\n"
173+
"unallocated.value {unallocated}\n"
174+
"total.value {total}\n")
175+
print(template.format(**usage_info))
137176

138177

139178
def filter_env_mounts(mounts):

0 commit comments

Comments
 (0)