from ..base import BaseExporter import subprocess class CustomExporter(BaseExporter): def metric_config(self): return { "xfs_disk_avail_bytes": {"type": "Gauge", "labels": ["user_id"]}, "xfs_disk_used_bytes": {"type": "Gauge", "labels": ["user_id"]}, } def generate(self): disk_avail_bytes = self.metrics.get('xfs_disk_avail_bytes') disk_used_bytes = self.metrics.get('xfs_disk_used_bytes') for user_id, usage in self._get_xfs_user_quota(mount=self.args[0]).items(): disk_used_bytes.labels(user_id).set(usage['bytes_used']) disk_avail_bytes.labels(user_id).set((usage['bytes_total'] - usage['bytes_used'])) def _get_xfs_user_quota(self, mount): script = "xfs_quota -x -c 'report -N -bnui' %s" % mount result = subprocess.run(["bash", "-c", script], capture_output=True, text=True) data = {} for line in result.stdout.strip().splitlines(): xfs_fields = line.split() key = xfs_fields[0].lstrip("#") if float(key) >= 10000: try: data[key] = self._parse_xfs_fields(xfs_fields) except Exception: # this line is not parseable continue return data def _parse_xfs_fields(self, xfs_fields): return { 'bytes_used': float(xfs_fields[1]) * 1000, 'bytes_total': float(xfs_fields[3]) * 1000, 'inodes_used': float(xfs_fields[6]), 'inodes_total': float(xfs_fields[8]) }