Skip to content

Commit e0cc9e7

Browse files
committed
dfstat.py: macos version added
1 parent d408cfa commit e0cc9e7

File tree

1 file changed

+107
-0
lines changed
  • collectors/available/macos/long-lived

1 file changed

+107
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#!/usr/bin/env python
2+
# This file is part of tcollector.
3+
# Copyright (C) 2014 The tcollector Authors.
4+
#
5+
# This program is free software: you can redistribute it and/or modify it
6+
# under the terms of the GNU Lesser General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or (at your
8+
# option) any later version. This program is distributed in the hope that it
9+
# will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
10+
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11+
# General Public License for more details. You should have received a copy
12+
# of the GNU Lesser General Public License along with this program. If not,
13+
# see <http://www.gnu.org/licenses/>.
14+
"""disk space and inode counts for TSDB """
15+
#
16+
# dfstat.py
17+
#
18+
# df.bytes.total total size of fs
19+
# df.bytes.used bytes used
20+
# df.bytes.percentused percentage of bytes used
21+
# df.bytes.free bytes free
22+
# df.inodes.total number of inodes
23+
# df.inodes.used number of inodes
24+
# df.inodes.percentused percentage of inodes used
25+
# df.inodes.free number of inodes
26+
27+
# All metrics are tagged with mount= and fstype=
28+
# This makes it easier to exclude stuff like
29+
# tmpfs mounts from disk usage reports.
30+
31+
import os
32+
import re
33+
import sys
34+
import time
35+
import subprocess
36+
37+
from collectors.lib import utils
38+
39+
COLLECTION_INTERVAL = 60 # seconds
40+
41+
# File system types to ignore
42+
FSTYPE_IGNORE = frozenset([
43+
"devfs",
44+
"autofs",
45+
"map",
46+
"smbfs",
47+
])
48+
49+
PATTERN = re.compile(r'^(?P<device>\S*)\s+on\s+(?P<mount_point>\S*)\s+\((?P<fs_type>\S*),\s+(?P<options>[^)]+\))$', re.VERBOSE)
50+
51+
52+
def main():
53+
"""dfstats main loop"""
54+
utils.drop_privileges()
55+
56+
while True:
57+
ts = int(time.time())
58+
59+
output = subprocess.check_output(["mount"]).decode("utf-8")
60+
61+
for line in output.splitlines():
62+
match = PATTERN.match(line)
63+
64+
if match:
65+
fs_type = match.group('fs_type')
66+
if fs_type in FSTYPE_IGNORE:
67+
continue
68+
69+
mount_point = match.group('mount_point')
70+
try:
71+
r = os.statvfs(mount_point)
72+
except OSError as e:
73+
utils.err("can't get info for mount point: %s: %s" % (mount_point, e))
74+
print("can't get info for mount point: %s: %s" % (mount_point, e))
75+
continue
76+
77+
used = r.f_blocks - r.f_bfree
78+
79+
if r.f_blocks == 0:
80+
percent_used = 100
81+
else:
82+
percent_used = used * 100.0 / (used + r.f_bavail)
83+
84+
print(f"df.bytes.total {ts} {r.f_frsize * r.f_blocks} mount={mount_point} fstype={fs_type}")
85+
print(f"df.bytes.used {ts} {r.f_frsize * used} mount={mount_point} fstype={fs_type}")
86+
print(f"df.bytes.percentused {ts} {percent_used:.2f} mount={mount_point} fstype={fs_type}")
87+
print(f"df.bytes.free {ts} {r.f_frsize * r.f_bavail} mount={mount_point} fstype={fs_type}")
88+
89+
used = r.f_files - r.f_ffree
90+
91+
if r.f_files == 0:
92+
percent_used = 100
93+
else:
94+
percent_used = used * 100.0 / r.f_files
95+
96+
print(f"df.inodes.total {ts} {r.f_files} mount={mount_point} fstype={fs_type}")
97+
print(f"df.inodes.used {ts} {used} mount={mount_point} fstype={fs_type}")
98+
print(f"df.inodes.percentused {ts} {percent_used:.2f} mount={mount_point} fstype={fs_type}")
99+
print(f"df.inodes.free {ts} {r.f_ffree} mount={mount_point} fstype={fs_type}")
100+
101+
sys.stdout.flush()
102+
time.sleep(COLLECTION_INTERVAL)
103+
104+
105+
if __name__ == "__main__":
106+
sys.stdin.close()
107+
sys.exit(main())

0 commit comments

Comments
 (0)