Skip to content
Closed
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
72 changes: 72 additions & 0 deletions examples/prometheus/btrfs_error_exporter
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3

# Collect per-device btrfs filesystem errors.
# Based on btrfs_stats.py (https://git.io/JkTIi) but rewritten to use
# python-btrfs and not shell out multiple times to 'btrfs stats'.
#
# Written by Holger Hoffstätte <holger@applied-asynchrony.com>
#
# This file is part of python-btrfs.
#
# python-btrfs is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# python-btrfs is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with python-btrfs. If not, see <http://www.gnu.org/licenses/>.

import btrfs

def get_btrfs_errors(mountpoint):
"""Get per-device errors for a btrfs mount point.

Args:
mountpoint: (string) path to a mount point.

Yields:
(device, error_type, error_count, fsid) tuples, where:
device: (string) path to block device.
error_type: (string) type of btrfs error.
error_count: (int) number of btrfs errors of a given type.
fsid: (string) filesystem UUID.
"""
fs = btrfs.FileSystem(mountpoint)
for dev in fs.devices():
devname = fs.dev_info(dev.devid).path.strip("/dev/")
error_counters = fs.dev_stats(dev.devid).counters
for error_name in error_counters.keys():
yield devname, error_name, error_counters[error_name], fs.fsid

def btrfs_error_metrics():
"""Collect btrfs error metrics.

Returns:
a list of strings to be exposed as Prometheus metrics or None.
"""
metric = "node_btrfs_errors_total"
contents = [
"# TYPE %s counter" % metric,
"# HELP %s number of btrfs errors" % metric,
]

for mountpoint in btrfs.utils.mounted_filesystem_paths():
for device, error_type, error_count, fsid in get_btrfs_errors(mountpoint):
contents.append('%s{device="%s",mountpoint="%s",type="%s",uuid="%s"} %d' %
(metric, device, mountpoint, error_type, fsid, error_count))

if len(contents) > 2:
# return metrics if there are actual btrfs filesystems found
# (i.e. `contents` contains more than just TYPE and HELP).
return contents

if __name__ == "__main__":
contents = btrfs_error_metrics()
if contents is not None:
print("\n".join(contents))