#!/bin/sh # # Plugin for monitor JVM activity - Heap Usage - # # Usage: # # Symlink into /etc/munin/plugins/ and add the monitored # alias name like : # # ln -s /usr/share/munin/plugins/jstat__heap \ # /etc/munin/plugins/jstat__heap # This should, however, be given through autoconf and suggest. # # Requirements: # # You need to execute your Java program under jsvc provided by # http://jakarta.apache.org/commons/daemon/ # which enables you to run your Java program with specified # pid file with -pidfile option. # A Brief setup documentation is also available at # http://tomcat.apache.org/tomcat-5.5-doc/setup.html # # Target: # # Target Java Virtual Machine to monitor are: # Sun JDK 5.0 (http://java.sun.com/javase/) # Sun JDK 8.0 (http://java.sun.com/javase/) # BEA JRockit 5.0 (http://dev2dev.bea.com/jrockit/) # # Parameters: # # config (required) # # Config variables: # # pidfilepath - Which file path use. Defaults to '/var/run/jsvc.pid' # javahome - override automatic detection of JRE directory # graphtitle - Title of the graph (defaults to PID file location) # default_java_home=/usr/lib/jvm/default-java [ -e "$default_java_home" ] || default_java_home=/usr/local/java/jdk pidfilepath=${pidfilepath:-/var/run/jsvc.pid} graphtitle=${graphtitle:-$pidfilepath} JAVA_HOME=${javahome:-$default_java_home} export JAVA_HOME get_jdk_type() { local version if "${JAVA_HOME}/bin/java" -version 2>&1 | grep -qi 'jrockit'; then echo "bea" else version=$("${JAVA_HOME}/bin/java" -version 2>&1 | grep '^java version' | awk '{print $3}' | sed -e 's/\"//g' | cut -d'_' -f 1) if echo "$version" | grep -q '^1\.5\.'; then echo "sun15" else echo "sun" fi fi } print_config() { echo "graph_title Heap Usage $graphtitle" echo "graph_args --base 1024 -l 0" echo "graph_vlabel Heap Usage(Bytes)" echo "graph_info Heap Usage" echo "graph_category virtualization" if [ "${JDK_TYPE}" = "bea" ]; then echo "NurserySize.label NurserySize" echo "HeapSize.label HeapSize" echo "UsedHeapSize.label UsedHeapSize" echo "NurserySize.draw AREA" echo "HeapSize.draw STACK" echo "UsedHeapSize.draw STACK" else echo "Eden_Used.label Eden_Used" echo "Eden_Free.label Eden_Free" echo "Survivor0_Used.label Survivor0_Used" echo "Survivor0_Free.label Survivor0_Free" echo "Survivor1_Used.label Survivor1_Used" echo "Survivor1_Free.label Survivor1_Free" echo "Old_Used.label Old_Used" echo "Old_Free.label Old_Free" echo "Permanent_Used.label Permanent_Used" echo "Permanent_Free.label Permanent_Free" echo "Eden_Used.draw AREA" echo "Eden_Free.draw STACK" echo "Survivor0_Used.draw STACK" echo "Survivor0_Free.draw STACK" echo "Survivor1_Used.draw STACK" echo "Survivor1_Free.draw STACK" echo "Old_Used.draw STACK" echo "Old_Free.draw STACK" echo "Permanent_Used.draw STACK" echo "Permanent_Free.draw STACK" fi } print_stats() { local pid_num="$1" local awk_script if [ "${JDK_TYPE}" = "bea" ]; then # shellcheck disable=SC2016 awk_script='{ HeapSize = $1; NurserySize = $2; UsedHeapSize = $3; print "NurserySize.value " NurserySize * 1024; print "HeapSize.value " HeapSize * 1024; print "UsedHeapSize.value " UsedHeapSize * 1024; }' elif [ "${JDK_TYPE}" = "sun15" ]; then # shellcheck disable=SC2016 awk_script='{ S0C = $1; S1C = $2; S0U = $3; S1U = $4; EC = $5; EU = $6; OC = $7; OU = $8; PC = $9; PU = $10; S0F = S0C - S0U; S1F = S1C - S1U; EF = EC - EU; OF = OC - OU; PF = PC - PU; print "Eden_Used.value " EU * 1024; print "Eden_Free.value " EF * 1024; print "Survivor0_Used.value " S0U * 1024; print "Survivor0_Free.value " S0F * 1024; print "Survivor1_Used.value " S1U * 1024; print "Survivor1_Free.value " S1F * 1024; print "Old_Used.value " OU * 1024; print "Old_Free.value " OF * 1024; print "Permanent_Used.value " PU * 1024; print "Permanent_Free.value " PF * 1024; }' else # example output of jstat for Java 1.8: # S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT # 2048.0 2048.0 0.0 1344.0 694784.0 145013.5 1398272.0 414857.1 102400.0 96308.0 12544.0 11240.1 979 20.997 5 2.705 23.702 # shellcheck disable=SC2016 awk_script='{ S0C = $1; S1C = $2; S0U = $3; S1U = $4; EC = $5; EU = $6; OC = $7; OU = $8; MC = $9; MU = $10; S0F = S0C - S0U; S1F = S1C - S1U; EF = EC - EU; OF = OC - OU; MF = MC - MU; print "Eden_Used.value " EU * 1024; print "Eden_Free.value " EF * 1024; print "Survivor0_Used.value " S0U * 1024; print "Survivor0_Free.value " S0F * 1024; print "Survivor1_Used.value " S1U * 1024; print "Survivor1_Free.value " S1F * 1024; print "Old_Used.value " OU * 1024; print "Old_Free.value " OF * 1024; print "Permanent_Used.value " PU * 1024; print "Permanent_Free.value " MF * 1024; }' fi "${JAVA_HOME}/bin/jstat" -gc "$pid_num" | tail -1 | awk "$awk_script" } # # autoconf # if [ "$1" = "autoconf" ]; then if [ ! -x "${JAVA_HOME}/bin/jstat" ]; then echo "no (No jstat found in ${JAVA_HOME}/bin)" elif [ ! -f "$pidfilepath" ]; then echo "no (missing file $pidfilepath)" elif [ ! -r "$pidfilepath" ]; then echo "no (cannot read $pidfilepath)" else echo "yes" fi exit 0 fi JDK_TYPE=$(get_jdk_type) if [ "$1" = "config" ]; then print_config fi print_stats "$(cat "$pidfilepath")"