Skip to content

munin: metadata usage warning and critical levels #43

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 76 additions & 37 deletions examples/munin/plugins/btrfs_usage
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,55 @@
import btrfs
import os
import sys
from math import floor

def calculate_munin_values(fs):
# Get detailed usage statistics.
usage = fs.usage()

# Whatever happens, we should not stack the graph above this. IOW, the
# unallocated bytes we end up with is just whatever is left over after
# doing all other things.
left = usage.total

if not fs.mixed_groups():
data_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_DATA].used
data_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_DATA].allocated
metadata_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_METADATA].used
metadata_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_METADATA].allocated
left = left - data_allocated - metadata_allocated
usage_info = {
'data_used': data_used,
'data_allocated': data_allocated,
'data_unused': data_allocated - data_used,
'metadata_used': metadata_used,
'metadata_allocated': metadata_allocated,
'metadata_unused': metadata_allocated - metadata_used,
}
else:
mixed_type = btrfs.BLOCK_GROUP_DATA | btrfs.BLOCK_GROUP_METADATA
used = usage.block_group_type_usage[mixed_type].used
allocated = usage.block_group_type_usage[mixed_type].allocated
left -= allocated
usage_info = {
'data_metadata_used': used,
'data_metadata_unused': allocated-used,
}
system_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_SYSTEM].used
usage_info['system_used'] = system_used
system_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_SYSTEM].allocated
usage_info['system_unused'] = system_allocated - system_used
left -= system_allocated

usage_info['parity'] = usage.parity
left -= usage.parity
usage_info['non_alloc_reclaimable'] = usage.unallocatable_reclaimable
left -= usage.unallocatable_reclaimable
usage_info['non_alloc'] = usage.unallocatable_hard
usage_info['unallocated'] = max(left - usage.unallocatable_hard, 0)
usage_info['total'] = usage.total

return usage_info


def munin_config(fs):
Expand Down Expand Up @@ -48,6 +97,14 @@ def munin_config(fs):
print("metadata_unused.draw STACK")
print("metadata_unused.info Unused Metadata")
print("metadata_unused.colour 0000CC")

usage_info = calculate_munin_values(fs)
#Assuming metadata is allocated by 256MB chunks
available_unallocated_for_metadata = floor(usage_info['unallocated'] / (2**28)) * (2**28)
metadata_warning = int((usage_info['metadata_allocated'] * 0.15) - available_unallocated_for_metadata)
metadata_critical = int((usage_info['metadata_allocated'] * 0.10) - available_unallocated_for_metadata)
print("metadata_unused.warning {}:".format(metadata_warning))
print("metadata_unused.critical {}:".format(metadata_critical))
else:
print("data_metadata_used.label Used Data+Metadata")
print("data_metadata_used.draw AREA")
Expand Down Expand Up @@ -94,46 +151,28 @@ def munin_config(fs):
def munin_values(fs):
print("multigraph btrfs_usage_{0}".format(str(fs.fsid).replace('-', '_')))

# Get detailed usage statistics.
usage = fs.usage()

# Whatever happens, we should not stack the graph above this. IOW, the
# unallocated bytes we end up with is just whatever is left over after
# doing all other things.
left = usage.total
usage_info = calculate_munin_values(fs)

if not fs.mixed_groups():
data_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_DATA].used
data_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_DATA].allocated
metadata_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_METADATA].used
metadata_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_METADATA].allocated
print("data_used.value {}".format(data_used))
print("data_unused.value {}".format(data_allocated - data_used))
print("metadata_used.value {}".format(metadata_used))
print("metadata_unused.value {}".format(metadata_allocated - metadata_used))
left = left - data_allocated - metadata_allocated
template = (
"data_used.value {data_used}\n"
"data_unused.value {data_unused}\n"
"metadata_used.value {metadata_used}\n"
"metadata_unused.value {metadata_unused}\n")
else:
mixed_type = btrfs.BLOCK_GROUP_DATA | btrfs.BLOCK_GROUP_METADATA
used = usage.block_group_type_usage[mixed_type].used
allocated = usage.block_group_type_usage[mixed_type].allocated
print("data_metadata_used.value {}".format(used))
print("data_metadata_unused.value {}".format(allocated - used))
left -= allocated
system_used = usage.block_group_type_usage[btrfs.BLOCK_GROUP_SYSTEM].used
system_allocated = usage.block_group_type_usage[btrfs.BLOCK_GROUP_SYSTEM].allocated
print("system_used.value {}".format(system_used))
print("system_unused.value {}".format(system_allocated - system_used))
left -= system_allocated

print("parity.value {}".format(usage.parity))
left -= usage.parity
print("non_alloc_reclaimable.value {}".format(usage.unallocatable_reclaimable))
left -= usage.unallocatable_reclaimable
print("non_alloc.value {}".format(usage.unallocatable_hard))
left = max(left - usage.unallocatable_hard, 0)
print("unallocated.value {}".format(left))
print("total.value {}".format(usage.total))
print("")
template = (
"data_metadata_used.value {data_metadata_used}\n"
"data_metadata_unused.value {data_metadata_unused}\n")

template += (
"system_used.value {system_used}\n"
"system_unused.value {system_unused}\n"
"parity.value {parity}\n"
"non_alloc_reclaimable.value {non_alloc_reclaimable}\n"
"non_alloc.value {non_alloc}\n"
"unallocated.value {unallocated}\n"
"total.value {total}\n")
print(template.format(**usage_info))


def filter_env_mounts(mounts):
Expand Down