192 lines
5.7 KiB
Python
Executable File
192 lines
5.7 KiB
Python
Executable File
#
|
|
# Copyright (c) 2018 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
############################################################################
|
|
#
|
|
# This file is the collectd 'Platform CPU Usage' Monitor.
|
|
#
|
|
# The Platform CPU Usage is calculated as an averaged percentage of
|
|
# platform core usable since the previous sample.
|
|
#
|
|
# Init Function:
|
|
# - if 'worker_reserved.conf exists then query/store PLATFORM_CPU_LIST
|
|
#
|
|
############################################################################
|
|
import os
|
|
import collectd
|
|
|
|
debug = False
|
|
|
|
# general return codes
|
|
PASS = 0
|
|
FAIL = 1
|
|
|
|
PLUGIN = 'platform memory usage'
|
|
|
|
|
|
# CPU Control class
|
|
class MEM:
|
|
hostname = "" # hostname for sample notification message
|
|
cmd = '/proc/meminfo' # the query comment
|
|
value = float(0.0) # float value of memory usage
|
|
|
|
# meminfo values we care about
|
|
memTotal_kB = 0
|
|
memFree_kB = 0
|
|
buffers = 0
|
|
cached = 0
|
|
SReclaimable = 0
|
|
CommitLimit = 0
|
|
Committed_AS = 0
|
|
HugePages_Total = 0
|
|
Hugepagesize = 0
|
|
AnonPages = 0
|
|
|
|
# derived values
|
|
avail = 0
|
|
total = 0
|
|
strict = 0
|
|
|
|
|
|
# Instantiate the class
|
|
obj = MEM()
|
|
|
|
|
|
def config_func(config):
|
|
"""
|
|
Configure the memory usage plugin
|
|
"""
|
|
|
|
for node in config.children:
|
|
key = node.key.lower()
|
|
val = node.values[0]
|
|
|
|
if key == 'path':
|
|
obj.cmd = str(val)
|
|
collectd.info("%s configured query command: '%s'" %
|
|
(PLUGIN, obj.cmd))
|
|
return 0
|
|
|
|
collectd.info("%s no config command provided ; "
|
|
"defaulting to '%s'" %
|
|
(PLUGIN, obj.cmd))
|
|
|
|
|
|
# Load the hostname and kernel memory 'overcommit' setting.
|
|
def init_func():
|
|
# get current hostname
|
|
obj.hostname = os.uname()[1]
|
|
|
|
# get strict setting
|
|
#
|
|
# a value of 0 means "heuristic overcommit"
|
|
# a value of 1 means "always overcommit"
|
|
# a value of 2 means "don't overcommit".
|
|
#
|
|
# set strict true strict=1 if value is = 2
|
|
# otherwise strict is false strict=0 (default)
|
|
|
|
fn = '/proc/sys/vm/overcommit_memory'
|
|
if os.path.exists(fn):
|
|
with open(fn, 'r') as infile:
|
|
for line in infile:
|
|
if int(line) == 2:
|
|
obj.strict = 1
|
|
break
|
|
|
|
collectd.info("%s strict:%d" % (PLUGIN, obj.strict))
|
|
|
|
|
|
# Calculate the CPU usage sample
|
|
def read_func():
|
|
meminfo = {}
|
|
try:
|
|
with open(obj.cmd) as fd:
|
|
for line in fd:
|
|
meminfo[line.split(':')[0]] = line.split(':')[1].strip()
|
|
|
|
except EnvironmentError as e:
|
|
collectd.error("%s unable to read from %s ; str(e)" %
|
|
(PLUGIN, str(e)))
|
|
return FAIL
|
|
|
|
# remove the 'unit' (kB) suffix that might be on some of the lines
|
|
for line in meminfo:
|
|
# remove the units from the value read
|
|
value_unit = [u.strip() for u in meminfo[line].split(' ', 1)]
|
|
if len(value_unit) == 2:
|
|
value, unit = value_unit
|
|
meminfo[line] = float(value)
|
|
else:
|
|
meminfo[line] = float(meminfo[line])
|
|
|
|
obj.memTotal_kB = float(meminfo['MemTotal'])
|
|
obj.memFree_kB = float(meminfo['MemFree'])
|
|
obj.buffers = float(meminfo['Buffers'])
|
|
obj.cached = float(meminfo['Cached'])
|
|
obj.SReclaimable = float(meminfo['SReclaimable'])
|
|
obj.CommitLimit = float(meminfo['CommitLimit'])
|
|
obj.Committed_AS = float(meminfo['Committed_AS'])
|
|
obj.HugePages_Total = float(meminfo['HugePages_Total'])
|
|
obj.Hugepagesize = float(meminfo['Hugepagesize'])
|
|
obj.AnonPages = float(meminfo['AnonPages'])
|
|
|
|
# collectd.info("%s /proc/meminfo: %s" % (PLUGIN, meminfo))
|
|
# collectd.info("%s ---------------------------" % PLUGIN)
|
|
# collectd.info("%s memTotal_kB : %f" % (PLUGIN, obj.memTotal_kB))
|
|
# collectd.info("%s memFree_kB : %f" % (PLUGIN, obj.memFree_kB))
|
|
# collectd.info("%s Buffers : %f" % (PLUGIN, obj.buffers))
|
|
# collectd.info("%s Cached : %f" % (PLUGIN, obj.cached))
|
|
# collectd.info("%s SReclaimable : %f" % (PLUGIN, obj.SReclaimable))
|
|
# collectd.info("%s CommitLimit : %f" % (PLUGIN, obj.CommitLimit))
|
|
# collectd.info("%s Committed_AS : %f" % (PLUGIN, obj.Committed_AS))
|
|
# collectd.info("%s HugePages_Total: %f" % (PLUGIN, obj.HugePages_Total))
|
|
# collectd.info("%s AnonPages : %f" % (PLUGIN, obj.AnonPages))
|
|
|
|
obj.avail = float(float(obj.memFree_kB) +
|
|
float(obj.buffers) +
|
|
float(obj.cached) +
|
|
float(obj.SReclaimable))
|
|
obj.total = float(float(obj.avail) +
|
|
float(obj.AnonPages))
|
|
|
|
# collectd.info("%s ---------------------------" % PLUGIN)
|
|
# collectd.info("%s memTotal: %d" % (PLUGIN, obj.avail))
|
|
# collectd.info("%s memAvail: %d" % (PLUGIN, obj.total))
|
|
|
|
if obj.strict == 1:
|
|
obj.value = float(float(obj.Committed_AS) / float(obj.CommitLimit))
|
|
else:
|
|
obj.value = float(float(obj.AnonPages) / float(obj.total))
|
|
|
|
obj.value = float(float(obj.value) * 100)
|
|
|
|
# get numa node memory
|
|
# numa_node_files = []
|
|
# fn = "/sys/devices/system/node/"
|
|
# files = os.listdir(fn)
|
|
# for file in files:
|
|
# if 'node' in file:
|
|
# numa_node_files.append(fn + file)
|
|
# collectd.info("%s numa node files: %s" %
|
|
# (PLUGIN, numa_node_files))
|
|
|
|
collectd.debug('%s reports %.2f %% usage' %
|
|
(PLUGIN, obj.value))
|
|
|
|
# Dispatch usage value to collectd
|
|
val = collectd.Values(host=obj.hostname)
|
|
val.plugin = 'memory'
|
|
val.type = 'percent'
|
|
val.type_instance = 'used'
|
|
val.dispatch(values=[obj.value])
|
|
|
|
return PASS
|
|
|
|
|
|
collectd.register_config(config_func)
|
|
collectd.register_init(init_func)
|
|
collectd.register_read(read_func)
|