Skip to content
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

Draft: Collect UMA stats #185

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
74 changes: 53 additions & 21 deletions igcollect/freebsd_memory.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,71 @@
#!/usr/bin/env python
"""igcollect - FreeBSD Memory Usage

Copyright (c) 2016 InnoGames GmbH
Copyright (c) 2024 InnoGames GmbH
"""

from __future__ import print_function
import re
from argparse import ArgumentParser
from time import time
import sysctl

UMA_STATS = ('size', 'stats.frees', 'stats.allocs', 'stats.current')

def parse_args():
parser = ArgumentParser()
parser.add_argument('--prefix', default='memory')
return parser.parse_args()


def main():
args = parse_args()
now = str(int(time()))

mi = parse_memory_info()
mem_gap_sys = mi['physmem'] - mi['v_page']

template = args.prefix + '.{} {} ' + now
print(template.format('total', mi['physmem']))
print(template.format('active', mi['v_active']))
print(template.format('inactive', mi['v_inactive']))
print(template.format('wired', mi['v_wire']))
print(template.format('cache', mi['v_cache']))
print(template.format('free', mi['v_free']))
print(template.format('gap_sys', mem_gap_sys))

ui = parse_uma_info()
for zone, data in ui.items():
for metric, value in data.items():
print(template.format(f'uma.{zone}.{metric}', value))


# Fix for missing long types
def parse_sysctl_value(a):
if type(a.value) == bytearray:
return int.from_bytes(a.value, byteorder='little', signed=False)
return a.value


def parse_uma_info():
uma_info = {}

# The sysctl python module does not seem to dig into sysctl data correctly.
# It retrieves all OIDs with proper names but the values are always None.
# Fetch the list once, build the list of known UMA zones.
for line in sysctl.filter('vm.uma'):
s = line.name.split('.')
if len(s) == 3:
uma_info[s[2]] = {}

# Fetch the real data in a separate step only for wanted OIDs.
for oid in uma_info.keys():
for metric in UMA_STATS:
for line in sysctl.filter(f'vm.uma.{oid}.{metric}'):
uma_info[oid][metric] = parse_sysctl_value(line)
Comment on lines +63 to +64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really need this for loop?
The left side of the assignment doesn't change with the for, so you either have a single element or you are overwriting data.

uma_info[oid]['malloc'] = uma_info[oid]['size'] * uma_info[oid]['stats.current']

return uma_info

def parse_memory_info():
memory_info={}

Expand All @@ -28,31 +78,13 @@ def parse_memory_info():
# After multiplying by page size they are not _count anymore
if name.endswith('_count'):
name = name.replace('_count', '')
if type(line.value) == bytearray:
# py-sysctl lack support for CTLTYPE_U32
# https://lists.freebsd.org/pipermail/freebsd-current/2018-July/070344.html
value = int.from_bytes(line.value, byteorder='little', signed=False)
else:
value = line.value
value = parse_sysctl_value(line)
memory_info[name] = value * pagesize

return memory_info


def main():
args = parse_args()

mi = parse_memory_info()
mem_gap_sys = mi['physmem'] - mi['v_page']

template = args.prefix + '.{} {} ' + str(int(time()))
print(template.format('total', mi['physmem']))
print(template.format('active', mi['v_active']))
print(template.format('inactive', mi['v_inactive']))
print(template.format('wired', mi['v_wire']))
print(template.format('cache', mi['v_cache']))
print(template.format('free', mi['v_free']))
print(template.format('gap_sys', mem_gap_sys))

if __name__ == '__main__':
main()