Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Daemon thread that logs memory usage an load (for JRuby)
require 'logger'
class MonitorDaemon
LOG_FILE = 'monitor.log'
LOG_FILES_MAX = 10 * 1024 * 1024 # 10MB
LOG_FILES_KEEP = 10 # keep 10 (max 100MB)
LOGGER = begin
if $servlet_context && ENV_JAVA['catalina.base'] && # {tomcat_base}/logs
File.directory?( logs = File.join(ENV_JAVA['catalina.base'], 'logs') )
Logger.new File.join(logs, LOG_FILE), LOG_FILES_KEEP, LOG_FILES_MAX
else
Logger.new "log/#{LOG_FILE}", LOG_FILES_KEEP, LOG_FILES_MAX
end
end
def self.start; new.start end
def initialize; @done = nil end
def start
thread = Thread.new { log_usage while ! @done }
Kernel.at_exit { @done = true; thread.join(1) }
end
SEPARATOR = ' '.freeze
def log_usage
log = ''
log_system_load_with_process log
log << SEPARATOR
log_heap_mem_usage log
log << SEPARATOR
log_metaspace_usage log
log << SEPARATOR
log_class_space_usage log
LOGGER.info log
sleep calc_sleep_time
rescue => e
LOGGER.warn "#{e.inspect}\n #{(e.backtrace || []).join("\n ")}"; @done = :error
end
def log_heap_mem_usage(log)
usage = get_heap_mem_usage
percent = (usage.used / usage.max.to_f) * 100
log << "HeapMem: #{format_bytes(usage.used)} / #{format_bytes(usage.max)} #{sprintf('%#2d', percent)}%"
end
def log_metaspace_usage(log)
return unless usage = get_metaspace_usage
if usage.max == -1
log << "MetaSpace: #{format_bytes(usage.used)} / #{'undefined'} #{' -'}%"
else
percent = (usage.used / usage.max.to_f) * 100
log << "MetaSpace: #{format_bytes(usage.used)} / #{format_bytes(usage.max)} #{sprintf('%#2d', percent)}%"
end
end
def log_class_space_usage(log)
return unless usage = get_class_space_usage
percent = (usage.used / usage.max.to_f) * 100
log << "CompClassSpace: #{format_bytes(usage.used)} / #{format_bytes(usage.max)} #{sprintf('%#2d', percent)}%"
end
def log_system_load_with_process(log)
return log_system_load unless pcs = get_process_load_percent
return unless sys = get_system_load_average
log << "LoadAvg: #{sprintf "%#7.4f", sys.round(4)} - JVM Using: #{sprintf('%#2d', ((pcs * 1000) / 10.0))}%"
end
protected
def get_system_load_average
mem_mx = java.lang.management.ManagementFactory.getOperatingSystemMXBean
avg = mem_mx.getSystemLoadAverage; avg.to_i == -1 ? nil : avg
end
def get_process_load_percent
name = javax.management.ObjectName.getInstance("java.lang:type=OperatingSystem")
list = mbean_server.getAttributes name, ['ProcessCpuLoad']
return nil if list.empty?
list[0].value # ProcessCpuLoad is the % CPU of current JVM for the system
end
def get_heap_mem_usage
mem_mx = java.lang.management.ManagementFactory.getMemoryMXBean
mem_mx.getHeapMemoryUsage
end
def get_metaspace_usage # assuming Java 8
get_memory_pool_mxbean_usage /Metaspace/
end
def get_class_space_usage
get_memory_pool_mxbean_usage /Class Space/ # Compressed Class Space
end
def get_memory_pool_mxbean_usage(name_re)
pool_mx = java.lang.management.ManagementFactory.getMemoryPoolMXBeans
pool_mx = pool_mx.find { |pool| pool.name =~ name_re }
pool_mx ? pool_mx.getUsage : nil
end
private :get_memory_pool_mxbean_usage
def mbean_server
java.lang.management.ManagementFactory.getPlatformMBeanServer
end
#
def calc_sleep_time
normal, three_quart, geting_full = 15, 3, 1.5 # seconds
return normal unless usage = get_metaspace_usage
return geting_full if (usage.used / usage.max.to_f) >= 0.90
return three_quart if (usage.used / usage.max.to_f) >= 0.75
normal
end
private
def format_bytes(count)
sprintf "%#6.1f MB", (count / (1000 * 1024)).round(2)
end
end
MonitorDaemon.start if defined?(JRUBY_VERSION)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.