mirror of
https://github.com/munin-monitoring/contrib.git
synced 2025-07-22 02:51:03 +00:00
remove plugin in main munin distribution (jmx), and extract jmx2munin
This commit is contained in:
parent
7dbdcedaf0
commit
933f0ea70b
23 changed files with 685 additions and 0 deletions
8
plugins/java/jmx2munin/.gitignore
vendored
Normal file
8
plugins/java/jmx2munin/.gitignore
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
.DS_Store
|
||||
.classpath
|
||||
.project
|
||||
.fatjar
|
||||
target
|
||||
eclipse
|
||||
old
|
||||
bin
|
79
plugins/java/jmx2munin/README.md
Normal file
79
plugins/java/jmx2munin/README.md
Normal file
|
@ -0,0 +1,79 @@
|
|||
# jmx2munin
|
||||
|
||||
The [jmx2munin](http://github.com/tcurdt/jmx2munin) project exposes JMX MBean attributes to [Munin](http://munin-monitoring.org/).
|
||||
Some of it's features:
|
||||
|
||||
* strictly complies to the plugin format
|
||||
* exposes composite types like Lists, Maps, Set as useful as possible
|
||||
* String values can be mapped to numbers
|
||||
|
||||
# How to use
|
||||
|
||||
This is what the Munin script will call. So you should test this first. Of course with your parameters. This example expose all Cassandra information to Munin.
|
||||
|
||||
java -jar jmx2munin.jar \
|
||||
-url service:jmx:rmi:///jndi/rmi://localhost:8080/jmxrmi \
|
||||
-query "org.apache.cassandra.*:*"
|
||||
|
||||
The "url" parameters specifies the JMX URL, the query selects the MBeans (and optionally also the attributes) to expose.
|
||||
|
||||
java -jar jmx2munin.jar \
|
||||
-url service:jmx:rmi:///jndi/rmi://localhost:8080/jmxrmi \
|
||||
-query "org.apache.cassandra.*:*" \
|
||||
-attribute org_apache_cassandra_db_storageservice_livenodes_size
|
||||
|
||||
The script that does the actual interaction with munin you can find in the contrib section. It's the one you should link in the your Munin plugin directory.
|
||||
|
||||
:/etc/munin/plugins$ ls -la cassandra_*
|
||||
lrwxrwxrwx 1 root root 37 2011-04-07 19:58 cassandra_nodes_in_cluster -> /usr/share/munin/plugins/jmx2munin.sh
|
||||
|
||||
In the plugin conf you point to the correct configuration
|
||||
|
||||
[cassandra_*]
|
||||
env.query org.apache.cassandra.*:*
|
||||
|
||||
[cassandra_nodes_in_cluster]
|
||||
env.config cassandra/nodes_in_cluster
|
||||
|
||||
A possible configuration could look like this
|
||||
|
||||
graph_title Number of Nodes in Cluster
|
||||
graph_vlabel org_apache_cassandra_db_storageservice_livenodes_size
|
||||
org_apache_cassandra_db_storageservice_livenodes_size.label number of nodes
|
||||
|
||||
The script will extract the attributes from the config and caches the JMX results to reduce the load when showing many values.
|
||||
|
||||
# More advanced
|
||||
|
||||
Sometimes it can be useful to track String values by mapping them into an enum as they really describe states. To find this possible candidates you can call:
|
||||
|
||||
java -jar jmx2munin.jar \
|
||||
-url service:jmx:rmi:///jndi/rmi://localhost:8080/jmxrmi \
|
||||
-query "org.apache.cassandra.*:*" \
|
||||
list
|
||||
|
||||
It should output a list of possible candidates. This can now be turned into a enum configuration file:
|
||||
|
||||
[org.apache.cassandra.db.StorageService:OperationMode]
|
||||
0 = ^Normal
|
||||
1 = ^Client
|
||||
2 = ^Joining
|
||||
3 = ^Bootstrapping
|
||||
4 = ^Leaving
|
||||
5 = ^Decommissioned
|
||||
6 = ^Starting drain
|
||||
7 = ^Node is drained
|
||||
|
||||
Which you then can provide:
|
||||
|
||||
java -jar jmx2munin.jar \
|
||||
-url service:jmx:rmi:///jndi/rmi://localhost:8080/jmxrmi \
|
||||
-query "org.apache.cassandra.*:*" \
|
||||
-enums /path/to/enums.cfg
|
||||
|
||||
Now matching values get replaced by their numerical representation. On the left needs to be a unique number on the right side is a regular expression. If a string cannot be matched according to the spec "U" for "undefined" will be returned.
|
||||
|
||||
# License
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License")
|
||||
You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
@ -0,0 +1,3 @@
|
|||
graph_title Number of Nodes in Cluster
|
||||
graph_vlabel org_apache_cassandra_db_storageservice_livenodes_size
|
||||
org_apache_cassandra_db_storageservice_livenodes_size.label number of nodes
|
55
plugins/java/jmx2munin/contrib/jmx2munin.sh
Normal file
55
plugins/java/jmx2munin/contrib/jmx2munin.sh
Normal file
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash
|
||||
# [cassandra_nodes_in_cluster]
|
||||
# env.config cassandra/nodes_in_cluster
|
||||
# env.query org.apache.cassandra.*:*
|
||||
|
||||
if [ -z "$MUNIN_LIBDIR" ]; then
|
||||
MUNIN_LIBDIR="`dirname $(dirname "$0")`"
|
||||
fi
|
||||
|
||||
if [ -f "$MUNIN_LIBDIR/plugins/plugin.sh" ]; then
|
||||
. $MUNIN_LIBDIR/plugins/plugin.sh
|
||||
fi
|
||||
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
echo yes
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -z "$url" ]; then
|
||||
# this is very common so make it a default
|
||||
url="service:jmx:rmi:///jndi/rmi://127.0.0.1:8080/jmxrmi"
|
||||
fi
|
||||
|
||||
if [ -z "$config" -o -z "$query" -o -z "$url" ]; then
|
||||
echo "Configuration needs attributes config, query and optinally url"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
JMX2MUNIN_DIR="$MUNIN_LIBDIR/plugins"
|
||||
CONFIG="$JMX2MUNIN_DIR/jmx2munin.cfg/$config"
|
||||
|
||||
if [ "$1" = "config" ]; then
|
||||
cat "$CONFIG"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
JAR="$JMX2MUNIN_DIR/jmx2munin.jar"
|
||||
CACHED="/tmp/jmx2munin"
|
||||
|
||||
if test ! -f $CACHED || test `find "$CACHED" -mmin +2`; then
|
||||
|
||||
java -jar "$JAR" \
|
||||
-url "$url" \
|
||||
-query "$query" \
|
||||
$ATTRIBUTES \
|
||||
> $CACHED
|
||||
|
||||
echo "cached.value `date +%s`" >> $CACHED
|
||||
fi
|
||||
|
||||
ATTRIBUTES=`awk '/\.label/ { gsub(/\.label/,""); print $1 }' $CONFIG`
|
||||
|
||||
for ATTRIBUTE in $ATTRIBUTES; do
|
||||
grep $ATTRIBUTE $CACHED
|
||||
done
|
121
plugins/java/jmx2munin/pom.xml
Normal file
121
plugins/java/jmx2munin/pom.xml
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.vafer</groupId>
|
||||
<artifactId>jmx2munin</artifactId>
|
||||
<name>jmx2munin</name>
|
||||
<version>1.0</version>
|
||||
<description>
|
||||
Munin plugin to access JMX information
|
||||
</description>
|
||||
<url>http://github.com/tcurdt/jmx2munin</url>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>tcurdt</id>
|
||||
<name>Torsten Curdt</name>
|
||||
<email>tcurdt at vafer.org</email>
|
||||
<timezone>+1</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>Apache License 2</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git://github.com:tcurdt/jmx2munin.git</connection>
|
||||
<developerConnection>scm:git:git://github.com:tcurdt/jmx2munin.git</developerConnection>
|
||||
<url>http://github.com/tcurdt/jmx2munin/tree/master</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.beust</groupId>
|
||||
<artifactId>jcommander</artifactId>
|
||||
<version>1.17</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<forkMode>never</forkMode>
|
||||
<includes>
|
||||
<include>**/*TestCase.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/Abstract*</exclude>
|
||||
</excludes>
|
||||
<testFailureIgnore>true</testFailureIgnore>
|
||||
<skip>false</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<version>2.1</version>
|
||||
<configuration>
|
||||
<attach>true</attach>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>create-source-jar</id>
|
||||
<goals>
|
||||
<goal>jar-no-fork</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<minimizeJar>false</minimizeJar>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>com.beust:jcommander</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>org.vafer.jmx.munin.Munin</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,77 @@
|
|||
package org.vafer.jmx;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
public final class Enums {
|
||||
|
||||
private TreeMap<String, LinkedHashMap<Integer, Pattern>> sections = new TreeMap<String, LinkedHashMap<Integer, Pattern>>();
|
||||
|
||||
public boolean load(String filePath) throws IOException {
|
||||
BufferedReader input = null;
|
||||
LinkedHashMap<Integer, Pattern> section = new LinkedHashMap<Integer, Pattern>();
|
||||
try {
|
||||
input = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
|
||||
String line;
|
||||
int linenr = 0;
|
||||
while((line = input.readLine()) != null) {
|
||||
linenr += 1;
|
||||
line = line.trim();
|
||||
if (line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith("[") && line.endsWith("]")) {
|
||||
// new section
|
||||
String id = line.substring(1, line.length() - 1);
|
||||
section = new LinkedHashMap<Integer, Pattern>();
|
||||
sections.put(id, section);
|
||||
} else {
|
||||
String[] pair = line.split("=");
|
||||
if (pair.length == 2) {
|
||||
Integer number = Integer.parseInt(pair[0].trim());
|
||||
Pattern pattern = Pattern.compile(pair[1].trim());
|
||||
if (section.put(number, pattern) != null) {
|
||||
System.err.println("Line " + linenr + ": previous definitions of " + number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (input != null) {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String id(ObjectName beanName, String attributeName) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(beanName.getDomain());
|
||||
sb.append('.');
|
||||
sb.append(beanName.getKeyProperty("type"));
|
||||
sb.append(':');
|
||||
sb.append(attributeName);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Number resolve(String id, String value) {
|
||||
LinkedHashMap<Integer, Pattern> section = sections.get(id);
|
||||
if (section == null) {
|
||||
return null;
|
||||
}
|
||||
for(Map.Entry<Integer, Pattern> entry : section.entrySet()) {
|
||||
if (entry.getValue().matcher(value).matches()) {
|
||||
return entry.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.vafer.jmx;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
public interface Filter {
|
||||
|
||||
public boolean include(ObjectName bean, String attribute);
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.vafer.jmx;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
public final class ListOutput implements Output {
|
||||
|
||||
private final Set<String> seen = new HashSet<String>();
|
||||
|
||||
public void output(ObjectName beanName, String attributeName, Object value) {
|
||||
Value.flatten(beanName, attributeName, value, new Value.Listener() {
|
||||
public void value(ObjectName beanName, String attributeName, String value) {
|
||||
final String id = Enums.id(beanName, attributeName);
|
||||
if (!seen.contains(id)) {
|
||||
System.out.println("[" + id + "]");
|
||||
seen.add(id);
|
||||
}
|
||||
}
|
||||
public void value(ObjectName beanName, String attributeName, Number value) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.vafer.jmx;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
public final class NoFilter implements Filter {
|
||||
|
||||
public boolean include(ObjectName bean, String attribute) {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package org.vafer.jmx;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
public interface Output {
|
||||
|
||||
public void output(ObjectName beanName, String attributeName, Object value);
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.vafer.jmx;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.InstanceNotFoundException;
|
||||
import javax.management.IntrospectionException;
|
||||
import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanInfo;
|
||||
import javax.management.MBeanServerConnection;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectInstance;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
public final class Query {
|
||||
|
||||
public void run(String url, String expression, Filter filter, Output output) throws IOException, MalformedObjectNameException, InstanceNotFoundException, ReflectionException, IntrospectionException, AttributeNotFoundException, MBeanException {
|
||||
JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL(url));
|
||||
MBeanServerConnection connection = connector.getMBeanServerConnection();
|
||||
final Collection<ObjectInstance> mbeans = connection.queryMBeans(new ObjectName(expression), null);
|
||||
|
||||
for(ObjectInstance mbean : mbeans) {
|
||||
final ObjectName mbeanName = mbean.getObjectName();
|
||||
final MBeanInfo mbeanInfo = connection.getMBeanInfo(mbeanName);
|
||||
final MBeanAttributeInfo[] attributes = mbeanInfo.getAttributes();
|
||||
for (final MBeanAttributeInfo attribute : attributes) {
|
||||
if (attribute.isReadable()) {
|
||||
if (filter.include(mbeanName, attribute.getName())) {
|
||||
final String attributeName = attribute.getName();
|
||||
try {
|
||||
output.output(
|
||||
mbean.getObjectName(),
|
||||
attributeName,
|
||||
connection.getAttribute(mbeanName, attributeName)
|
||||
);
|
||||
} catch(Exception e) {
|
||||
// System.err.println("Failed to read " + mbeanName + "." + attributeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
connector.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.vafer.jmx;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
public final class Value {
|
||||
|
||||
public interface Listener {
|
||||
public void value(ObjectName beanName, String attributeName, String value);
|
||||
public void value(ObjectName beanName, String attributeName, Number value);
|
||||
}
|
||||
|
||||
public static void flatten(ObjectName beanName, String attributeName, Object value, Listener listener) {
|
||||
if (value instanceof Number) {
|
||||
|
||||
listener.value(beanName, attributeName, (Number) value);
|
||||
|
||||
} else if (value instanceof String) {
|
||||
|
||||
listener.value(beanName, attributeName, (String) value);
|
||||
|
||||
} else if (value instanceof Set) {
|
||||
|
||||
final Set set = (Set) value;
|
||||
flatten(beanName, attributeName + ".size", set.size(), listener);
|
||||
for(Object entry : set) {
|
||||
flatten(beanName, attributeName + "[" + entry + "]", 1, listener);
|
||||
}
|
||||
|
||||
} else if (value instanceof List) {
|
||||
|
||||
final List list = (List)value;
|
||||
listener.value(beanName, attributeName + ".size", list.size());
|
||||
for(int i = 0; i<list.size(); i++) {
|
||||
flatten(beanName, attributeName + "[" + i + "]", list.get(i), listener);
|
||||
}
|
||||
|
||||
} else if (value instanceof Map) {
|
||||
|
||||
final Map<?,?> map = (Map<?,?>) value;
|
||||
listener.value(beanName, attributeName + ".size", map.size());
|
||||
for(Map.Entry<?, ?> entry : map.entrySet()) {
|
||||
flatten(beanName, attributeName + "[" + entry.getKey() + "]", entry.getValue(), listener);
|
||||
}
|
||||
|
||||
} else {
|
||||
// System.err.println("Failed to convert " + beanName + "." + attributeName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package org.vafer.jmx.munin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.vafer.jmx.Enums;
|
||||
import org.vafer.jmx.Filter;
|
||||
import org.vafer.jmx.ListOutput;
|
||||
import org.vafer.jmx.NoFilter;
|
||||
import org.vafer.jmx.Query;
|
||||
|
||||
import com.beust.jcommander.JCommander;
|
||||
import com.beust.jcommander.Parameter;
|
||||
|
||||
public final class Munin {
|
||||
|
||||
@Parameter(description = "")
|
||||
private List<String> args = new ArrayList<String>();
|
||||
|
||||
@Parameter(names = "-url", description = "jmx url", required = true)
|
||||
private String url;
|
||||
|
||||
@Parameter(names = "-query", description = "query expression", required = true)
|
||||
private String query;
|
||||
|
||||
@Parameter(names = "-enums", description = "file string to enum config")
|
||||
private String enumsPath;
|
||||
|
||||
@Parameter(names = "-attribute", description = "attributes to return")
|
||||
private List<String> attributes = new ArrayList<String>();
|
||||
|
||||
private void run() throws Exception {
|
||||
final Filter filter;
|
||||
if (attributes == null || attributes.isEmpty()) {
|
||||
filter = new NoFilter();
|
||||
} else {
|
||||
filter = new MuninAttributesFilter(attributes);
|
||||
}
|
||||
|
||||
final Enums enums = new Enums();
|
||||
if (enumsPath != null) {
|
||||
enums.load(enumsPath);
|
||||
}
|
||||
|
||||
final String cmd = args.toString().toLowerCase(Locale.US);
|
||||
if ("[list]".equals(cmd)) {
|
||||
new Query().run(url, query, filter, new ListOutput());
|
||||
} else {
|
||||
new Query().run(url, query, filter, new MuninOutput(enums));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Munin m = new Munin();
|
||||
|
||||
JCommander cli = new JCommander(m);
|
||||
try {
|
||||
cli.parse(args);
|
||||
} catch(Exception e) {
|
||||
cli.usage();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
m.run();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.vafer.jmx.munin;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.vafer.jmx.Filter;
|
||||
|
||||
public final class MuninAttributesFilter implements Filter {
|
||||
|
||||
private final HashSet<String> attributes = new HashSet<String>();
|
||||
|
||||
public MuninAttributesFilter(List<String> pAttributes) {
|
||||
for (String attribute : pAttributes) {
|
||||
attributes.add(attribute.trim().replaceAll("_size$", ""));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean include(ObjectName bean, String attribute) {
|
||||
return attributes.contains(MuninOutput.attributeName(bean, attribute));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package org.vafer.jmx.munin;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.vafer.jmx.Enums;
|
||||
import org.vafer.jmx.Output;
|
||||
import org.vafer.jmx.Value;
|
||||
|
||||
public final class MuninOutput implements Output {
|
||||
|
||||
private final Enums enums;
|
||||
|
||||
public MuninOutput(Enums enums) {
|
||||
this.enums = enums;
|
||||
}
|
||||
|
||||
public static String attributeName(ObjectName bean, String attribute) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(fieldname(beanString(bean)));
|
||||
sb.append('_');
|
||||
sb.append(fieldname(attribute));
|
||||
return sb.toString().toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
private static String fieldname(String s) {
|
||||
return s.replaceAll("[^A-Za-z0-9]", "_");
|
||||
}
|
||||
|
||||
private static String beanString(ObjectName beanName) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(beanName.getDomain());
|
||||
|
||||
Hashtable<String, String> properties = beanName.getKeyPropertyList();
|
||||
|
||||
String keyspace = "keyspace";
|
||||
if (properties.containsKey(keyspace)) {
|
||||
sb.append('.');
|
||||
sb.append(properties.get(keyspace));
|
||||
properties.remove(keyspace);
|
||||
}
|
||||
|
||||
String type = "type";
|
||||
if (properties.containsKey(type)) {
|
||||
sb.append('.');
|
||||
sb.append(properties.get(type));
|
||||
properties.remove(type);
|
||||
}
|
||||
|
||||
ArrayList<String> keys = new ArrayList(properties.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
for(String key : keys) {
|
||||
sb.append('.');
|
||||
sb.append(properties.get(key));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
// return beanName.getCanonicalName();
|
||||
}
|
||||
|
||||
public void output(ObjectName beanName, String attributeName, Object value) {
|
||||
Value.flatten(beanName, attributeName, value, new Value.Listener() {
|
||||
public void value(ObjectName beanName, String attributeName, String value) {
|
||||
final Number v = enums.resolve(Enums.id(beanName, attributeName), value);
|
||||
if (v != null) {
|
||||
value(beanName, attributeName, v);
|
||||
} else {
|
||||
value(beanName, attributeName, Double.NaN);
|
||||
}
|
||||
}
|
||||
public void value(ObjectName beanName, String attributeName, Number value) {
|
||||
final String v;
|
||||
|
||||
if (Double.isNaN(value.doubleValue())) {
|
||||
v = "U";
|
||||
} else {
|
||||
final NumberFormat f = NumberFormat.getInstance();
|
||||
f.setMaximumFractionDigits(2);
|
||||
f.setGroupingUsed(false);
|
||||
v = f.format(value);
|
||||
}
|
||||
|
||||
System.out.println(attributeName(beanName, attributeName) + ".value " + v);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
218
plugins/java/jstat__gccount
Executable file
218
plugins/java/jstat__gccount
Executable file
|
@ -0,0 +1,218 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Plugin for monitor JVM activity - GC Count -
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# Symlink into /etc/munin/plugins/ and add the monitored
|
||||
# alias name like :
|
||||
#
|
||||
# ln -s /usr/share/munin/plugins/jstat__gccount \
|
||||
# /etc/munin/plugins/jstat_<jvm alias>_gccount
|
||||
# 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/) (default)
|
||||
# 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 - Defaults to '/usr/local/java/jdk'
|
||||
#
|
||||
DefaultPidFile="/var/run/jsvc.pid"
|
||||
DefaultJavaHome="/usr/local/java/jdk"
|
||||
|
||||
#
|
||||
# Environment Variables
|
||||
#
|
||||
if [ -z "${pidfilepath}" ]; then
|
||||
pidfilepath="${DefaultPidFile}"
|
||||
fi
|
||||
|
||||
if [ -z "${graphtitle}" ]; then
|
||||
graphtitle="${pidfilepath}"
|
||||
fi
|
||||
|
||||
if [ -z "${javahome}" ]; then
|
||||
JAVA_HOME="${DefaultJavaHome}"
|
||||
else
|
||||
JAVA_HOME="${javahome}"
|
||||
fi
|
||||
export JAVA_HOME
|
||||
|
||||
#
|
||||
# Functions
|
||||
#
|
||||
chk_jdk()
|
||||
{
|
||||
isJRockit=`${JAVA_HOME}/bin/java -version 2>&1 | egrep -i 'jrockit'`
|
||||
if [ -n "${isJRockit}" ]; then
|
||||
JDK_TYPE="bea"
|
||||
else
|
||||
JDK_TYPE="sun"
|
||||
fi
|
||||
}
|
||||
|
||||
chk_version()
|
||||
{
|
||||
Version=`${JAVA_HOME}/bin/java -version 2>&1 | egrep '^java version' | awk '{print $3}' | sed -e 's/\"//g' | cut -d'_' -f 1`
|
||||
if [ "${Version}" != "1.5.0" ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
config_common()
|
||||
{
|
||||
echo 'graph_title GC Count' $graphtitle
|
||||
echo 'graph_args -l 0'
|
||||
echo 'graph_vlabel GC Count(times)'
|
||||
echo 'graph_total total'
|
||||
echo 'graph_info GC Count'
|
||||
echo 'graph_category JVM'
|
||||
}
|
||||
|
||||
config_sun_jdk()
|
||||
{
|
||||
config_common
|
||||
|
||||
echo 'Young_GC.label Young_GC'
|
||||
echo 'Young_GC.min 0'
|
||||
echo 'Full_GC.label Full_GC'
|
||||
echo 'Full_GC.min 0'
|
||||
|
||||
}
|
||||
|
||||
config_bea_jdk()
|
||||
{
|
||||
config_common
|
||||
|
||||
echo 'Young_GC.label Young_GC'
|
||||
echo 'Young_GC.min 0'
|
||||
echo 'Old_GC.label Old_GC'
|
||||
echo 'Old_GC.min 0'
|
||||
}
|
||||
|
||||
print_sun_stats()
|
||||
{
|
||||
${JAVA_HOME}/bin/jstat -gc ${PidNum} | tail -1 | awk \
|
||||
'{\
|
||||
S0C = $1; \
|
||||
S1C = $2; \
|
||||
S0U = $3; \
|
||||
S1U = $4; \
|
||||
EC = $5; \
|
||||
EU = $6; \
|
||||
OC = $7; \
|
||||
OU = $8; \
|
||||
PC = $9; \
|
||||
PU = $10; \
|
||||
YGC = $11; \
|
||||
YGCT = $12; \
|
||||
FGC = $13; \
|
||||
FGCT = $14; \
|
||||
GCT = $15; \
|
||||
\
|
||||
S0F = S0C - S0U; \
|
||||
S1F = S1C - S1U; \
|
||||
EF = EC - EU; \
|
||||
OF = OC - OU; \
|
||||
PF = PC - PU; \
|
||||
\
|
||||
print "Young_GC.value " YGC; \
|
||||
print "Full_GC.value " FGC; \
|
||||
}'
|
||||
}
|
||||
|
||||
print_bea_stats()
|
||||
{
|
||||
${JAVA_HOME}/bin/jstat -gc ${PidNum} | tail -1 | awk \
|
||||
'{\
|
||||
HeapSize = $1; \
|
||||
NurserySize = $2; \
|
||||
UsedHeapSize = $3; \
|
||||
YC = $4; \
|
||||
OC = $5; \
|
||||
YCTime = $6; \
|
||||
OCTime = $7; \
|
||||
GCTime = $8; \
|
||||
YCPauseTime = $9; \
|
||||
OCPauseTime = $10; \
|
||||
PauseTime = $11; \
|
||||
Finalizers = $12; \
|
||||
\
|
||||
print "Young_GC.value " YC; \
|
||||
print "Old_GC.value " OC;\
|
||||
}'
|
||||
}
|
||||
|
||||
#
|
||||
# common for all argument
|
||||
#
|
||||
chk_jdk
|
||||
|
||||
#
|
||||
# autoconf
|
||||
#
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
|
||||
if [ ! -x "${JAVA_HOME}/bin/jstat" ]; then
|
||||
echo "no (No jstat found in ${JAVA_HOME}/bin)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chk_version
|
||||
if [ $? != 0 ]; then
|
||||
echo "no (Java version is invalid)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "${pidfilepath}" -o ! -r "${pidfilepath}" ]; then
|
||||
echo "no (No such file ${pidfilepath} or cannot read ${pidfilepath}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "yes"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# config
|
||||
#
|
||||
if [ "$1" = "config" ]; then
|
||||
if [ "${JDK_TYPE}" == "bea" ]; then
|
||||
config_bea_jdk
|
||||
else
|
||||
config_sun_jdk
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#
|
||||
# Main
|
||||
#
|
||||
PidNum=`cat ${pidfilepath}`
|
||||
|
||||
if [ "${JDK_TYPE}" == "bea" ]; then
|
||||
print_bea_stats
|
||||
else
|
||||
print_sun_stats
|
||||
fi
|
226
plugins/java/jstat__gctime
Executable file
226
plugins/java/jstat__gctime
Executable file
|
@ -0,0 +1,226 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Plugin for monitor JVM activity - GC Time -
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# Symlink into /etc/munin/plugins/ and add the monitored
|
||||
# alias name like :
|
||||
#
|
||||
# ln -s /usr/share/munin/plugins/jstat__gctime \
|
||||
# /etc/munin/plugins/jstat_<jvm alias>_gctime
|
||||
# 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/) (default)
|
||||
# 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 - Defaults to '/usr/local/java/jdk'
|
||||
#
|
||||
DefaultPidFile="/var/run/jsvc.pid"
|
||||
DefaultJavaHome="/usr/local/java/jdk"
|
||||
|
||||
#
|
||||
# Environment Variables
|
||||
#
|
||||
if [ -z "${pidfilepath}" ]; then
|
||||
pidfilepath="${DefaultPidFile}"
|
||||
fi
|
||||
|
||||
if [ -z "${graphtitle}" ]; then
|
||||
graphtitle="${pidfilepath}"
|
||||
fi
|
||||
|
||||
if [ -z "${javahome}" ]; then
|
||||
JAVA_HOME="${DefaultJavaHome}"
|
||||
else
|
||||
JAVA_HOME="${javahome}"
|
||||
fi
|
||||
export JAVA_HOME
|
||||
|
||||
#
|
||||
# Functions
|
||||
#
|
||||
chk_jdk()
|
||||
{
|
||||
isJRockit=`${JAVA_HOME}/bin/java -version 2>&1 | egrep -i 'jrockit'`
|
||||
if [ -n "${isJRockit}" ]; then
|
||||
JDK_TYPE="bea"
|
||||
else
|
||||
JDK_TYPE="sun"
|
||||
fi
|
||||
}
|
||||
|
||||
chk_version()
|
||||
{
|
||||
Version=`${JAVA_HOME}/bin/java -version 2>&1 | egrep '^java version' | awk '{print $3}' | sed -e 's/\"//g' | cut -d'_' -f 1`
|
||||
if [ "${Version}" != "1.5.0" ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
config_common()
|
||||
{
|
||||
echo 'graph_title GC Time' $graphtitle
|
||||
echo 'graph_args -l 0'
|
||||
echo 'graph_vlabel GC Time(sec)'
|
||||
echo 'graph_total total'
|
||||
echo 'graph_info GC Time'
|
||||
echo 'graph_category JVM'
|
||||
}
|
||||
|
||||
config_sun_jdk()
|
||||
{
|
||||
config_common
|
||||
|
||||
echo 'Young_GC.label Young_GC'
|
||||
echo 'Young_GC.min 0'
|
||||
echo 'Full_GC.label Full_GC'
|
||||
echo 'Full_GC.min 0'
|
||||
|
||||
}
|
||||
|
||||
config_bea_jdk()
|
||||
{
|
||||
config_common
|
||||
|
||||
echo 'Young_GC.label Young_GC'
|
||||
echo 'Young_GC.min 0'
|
||||
echo 'Old_GC.label Old_GC'
|
||||
echo 'Old_GC.min 0'
|
||||
echo 'Young_Pause.label Young_GC Pause'
|
||||
echo 'Young_Pause.min 0'
|
||||
echo 'Old_Pause.label Old_GC Pause'
|
||||
echo 'Old_Pause.min 0'
|
||||
|
||||
}
|
||||
|
||||
print_sun_stats()
|
||||
{
|
||||
${JAVA_HOME}/bin/jstat -gc ${PidNum} | tail -1 | awk \
|
||||
'{\
|
||||
S0C = $1; \
|
||||
S1C = $2; \
|
||||
S0U = $3; \
|
||||
S1U = $4; \
|
||||
EC = $5; \
|
||||
EU = $6; \
|
||||
OC = $7; \
|
||||
OU = $8;
|
||||
PC = $9; \
|
||||
PU = $10; \
|
||||
YGC = $11; \
|
||||
YGCT = $12; \
|
||||
FGC = $13; \
|
||||
FGCT = $14; \
|
||||
GCT = $15; \
|
||||
|
||||
\
|
||||
S0F = S0C - S0U; \
|
||||
S1F = S1C - S1U; \
|
||||
EF = EC - EU; \
|
||||
OF = OC - OU; \
|
||||
PF = PC - PU; \
|
||||
\
|
||||
print "Young_GC.value " YGCT; \
|
||||
print "Full_GC.value " FGCT; \
|
||||
}'
|
||||
}
|
||||
|
||||
print_bea_stats()
|
||||
{
|
||||
${JAVA_HOME}/bin/jstat -gc ${PidNum} | tail -1 | awk \
|
||||
'{\
|
||||
HeapSize = $1; \
|
||||
NurserySize = $2; \
|
||||
UsedHeapSize = $3; \
|
||||
YC = $4; \
|
||||
OC = $5; \
|
||||
YCTime = $6; \
|
||||
OCTime = $7; \
|
||||
GCTime = $8; \
|
||||
YCPauseTime = $9; \
|
||||
OCPauseTime = $10; \
|
||||
PauseTime = $11; \
|
||||
Finalizers = $12; \
|
||||
\
|
||||
print "Young_GC.value " YCTime; \
|
||||
print "Old_GC.value " OCTime; \
|
||||
print "Young_Pause.value " YCPauseTime; \
|
||||
print "Old_Pause.value " OCPauseTime
|
||||
}'
|
||||
}
|
||||
|
||||
#
|
||||
# common for all argument
|
||||
#
|
||||
chk_jdk
|
||||
|
||||
#
|
||||
# autoconf
|
||||
#
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
|
||||
if [ ! -x "${JAVA_HOME}/bin/jstat" ]; then
|
||||
echo "no (No jstat found in ${JAVA_HOME}/bin)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chk_version
|
||||
if [ $? != 0 ]; then
|
||||
echo "no (Java version is invalid)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "${pidfilepath}" -o ! -r "${pidfilepath}" ]; then
|
||||
echo "no (No such file ${pidfilepath} or cannot read ${pidfilepath}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "yes"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# config
|
||||
#
|
||||
if [ "$1" = "config" ]; then
|
||||
if [ "${JDK_TYPE}" == "bea" ]; then
|
||||
config_bea_jdk
|
||||
else
|
||||
config_sun_jdk
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#
|
||||
# Main
|
||||
#
|
||||
PidNum=`cat ${pidfilepath}`
|
||||
|
||||
if [ "${JDK_TYPE}" == "bea" ]; then
|
||||
print_bea_stats
|
||||
else
|
||||
print_sun_stats
|
||||
fi
|
238
plugins/java/jstat__heap
Executable file
238
plugins/java/jstat__heap
Executable file
|
@ -0,0 +1,238 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# 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_<jvm alias>_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/) (default)
|
||||
# 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 - Defaults to '/usr/local/java/jdk'
|
||||
#
|
||||
DefaultPidFile="/var/run/jsvc.pid"
|
||||
DefaultJavaHome="/usr/local/java/jdk"
|
||||
|
||||
#
|
||||
# Environment Variables
|
||||
#
|
||||
if [ -z "${pidfilepath}" ]; then
|
||||
pidfilepath="${DefaultPidFile}"
|
||||
fi
|
||||
|
||||
if [ -z "${graphtitle}" ]; then
|
||||
graphtitle="${pidfilepath}"
|
||||
fi
|
||||
|
||||
if [ -z "${javahome}" ]; then
|
||||
JAVA_HOME="${DefaultJavaHome}"
|
||||
else
|
||||
JAVA_HOME="${javahome}"
|
||||
fi
|
||||
export JAVA_HOME
|
||||
|
||||
#
|
||||
# Functions
|
||||
#
|
||||
chk_jdk()
|
||||
{
|
||||
isJRockit=`${JAVA_HOME}/bin/java -version 2>&1 | egrep -i 'jrockit'`
|
||||
if [ -n "${isJRockit}" ]; then
|
||||
JDK_TYPE="bea"
|
||||
else
|
||||
JDK_TYPE="sun"
|
||||
fi
|
||||
}
|
||||
|
||||
chk_version()
|
||||
{
|
||||
Version=`${JAVA_HOME}/bin/java -version 2>&1 | egrep '^java version' | awk '{print $3}' | sed -e 's/\"//g' | cut -d'_' -f 1`
|
||||
if [ "${Version}" != "1.5.0" ]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
config_common()
|
||||
{
|
||||
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 JVM"
|
||||
}
|
||||
|
||||
config_sun_jdk()
|
||||
{
|
||||
config_common
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
config_bea_jdk()
|
||||
{
|
||||
config_common
|
||||
|
||||
echo "NurserySize.label NurserySize"
|
||||
echo "HeapSize.label HeapSize"
|
||||
echo "UsedHeapSize.label UsedHeapSize"
|
||||
echo "NurserySize.draw AREA"
|
||||
echo "HeapSize.draw STACK"
|
||||
echo "UsedHeapSize.draw STACK"
|
||||
}
|
||||
|
||||
print_sun_stats()
|
||||
{
|
||||
${JAVA_HOME}/bin/jstat -gc ${PidNum} | tail -1 | awk \
|
||||
'{\
|
||||
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; \
|
||||
}'
|
||||
}
|
||||
|
||||
print_bea_stats()
|
||||
{
|
||||
${JAVA_HOME}/bin/jstat -gc ${PidNum} | tail -1 | awk \
|
||||
'{\
|
||||
HeapSize = $1; \
|
||||
NurserySize = $2; \
|
||||
UsedHeapSize = $3; \
|
||||
YC = $4; \
|
||||
OC = $5; \
|
||||
YCTime = $6; \
|
||||
OCTime = $7; \
|
||||
GCTime = $8; \
|
||||
YCPauseTime = $9; \
|
||||
OCPauseTime = $10; \
|
||||
PauseTime = $11; \
|
||||
Finalizers = $12; \
|
||||
\
|
||||
print "NurserySize.value " NurserySize * 1024; \
|
||||
print "HeapSize.value " UsedHeapSize * 1024; \
|
||||
print "UsedHeapSize.value " UsedHeapSize * 1024; \
|
||||
}'
|
||||
}
|
||||
|
||||
#
|
||||
# common for all argument
|
||||
#
|
||||
chk_jdk
|
||||
|
||||
#
|
||||
# autoconf
|
||||
#
|
||||
if [ "$1" = "autoconf" ]; then
|
||||
|
||||
if [ ! -x "${JAVA_HOME}/bin/jstat" ]; then
|
||||
echo "no (No jstat found in ${JAVA_HOME}/bin)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chk_version
|
||||
if [ $? != 0 ]; then
|
||||
echo "no (Java version is invalid)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "${pidfilepath}" -o ! -r "${pidfilepath}" ]; then
|
||||
echo "no (No such file ${pidfilepath} or cannot read ${pidfilepath}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "yes"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# config
|
||||
#
|
||||
if [ "$1" = "config" ]; then
|
||||
if [ "${JDK_TYPE}" == "bea" ]; then
|
||||
config_bea_jdk
|
||||
else
|
||||
config_sun_jdk
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#
|
||||
# Main
|
||||
#
|
||||
PidNum=`cat ${pidfilepath}`
|
||||
|
||||
if [ "${JDK_TYPE}" == "bea" ]; then
|
||||
print_bea_stats
|
||||
else
|
||||
print_sun_stats
|
||||
fi
|
182
plugins/java/jvm_sun_memory
Executable file
182
plugins/java/jvm_sun_memory
Executable file
|
@ -0,0 +1,182 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Sun JVM memory statistics. Parses a verbose log of minor GC and
|
||||
# tenured GC stats.
|
||||
|
||||
# To determine the totalheap value it looks for maxmem stats (from a
|
||||
# tenured gc) in the last 5 minutes of the log file. If there are no
|
||||
# log lines in the last 5 minutes the value will be U(ndefined).
|
||||
|
||||
# Since the log lines are timestamped with seconds since the JVM
|
||||
# started we look at the last line of the log to determine when "now"
|
||||
# is for the JVM. In a reasonably active JVM there will be several
|
||||
# minor GCs a minute so the "now" approximation based on these log
|
||||
# lines are close enough.
|
||||
|
||||
# Configuration (common with the other sun_jvm_* plugins in this family):
|
||||
# [jvm_sun_*]
|
||||
# env.logfile /var/foo/java.log (default: /var/log/app/jvm/gc.log)
|
||||
# env.graphtitle (default: "Sun Java")
|
||||
|
||||
# You need to configure your Sun JVM with these options:
|
||||
# -verbose:gc
|
||||
# -Xloggc:/var/log/app/jvm/gc.log
|
||||
# -XX:+PrintGCTimeStamps
|
||||
# -XX:+PrintGCDetails
|
||||
|
||||
# History:
|
||||
|
||||
# This plugin was developed by various people over some time - no logs
|
||||
# of this has been found. - In 2006 significant contributions was
|
||||
# financed by NRK (Norwegian Broadcasting Coproration) and performed
|
||||
# by Nicolai Langfeldt of Linpro AS in Oslo, Norway.
|
||||
|
||||
# $Id: $
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Fcntl qw(:seek);
|
||||
|
||||
# Full path to jvm log file
|
||||
my $logfile = $ENV{logfile} || "/var/log/app/jvm/gc.log";
|
||||
my $grtitle = $ENV{graphtitle} || "Sun Java";
|
||||
|
||||
# Title that appears on munin graph
|
||||
my $title = "$grtitle memory usage";
|
||||
# Extended information that appears below munin graph
|
||||
my $info = "Write som info about this graph...";
|
||||
|
||||
sub analyze_record {
|
||||
# Match all interesting elements of a record and insert them
|
||||
# into a hash
|
||||
|
||||
my $record = shift;
|
||||
my %elements;
|
||||
|
||||
if ( $record =~
|
||||
m/(\d+\.\d+).+?(\d+\.\d+).+?DefNew: (\d+).+?(\d+).+?(\d+).+?(\d+\.\d+).+?(\d+\.\d+): \[Tenured(\[U.+\])*: (\d+).+?(\d+).+?(\d+).+?(\d+\.\d+).+?(\d+).+?(\d+).+?(\d+).+?(\d+\.\d+).+/
|
||||
) {
|
||||
%elements = (
|
||||
total_timestamp => $1,
|
||||
defnew_timestamp => $2,
|
||||
defnew_mem_from => $3*1024,
|
||||
defnew_mem_to => $4*1024,
|
||||
defnew_mem_max => $5*1024,
|
||||
defnew_time_used => $6,
|
||||
tenured_timestamp => $7,
|
||||
tenured_mem_from => $9*1024,
|
||||
tenured_mem_to => $10*1024,
|
||||
tenured_mem_max => $11*1024,
|
||||
tenured_time_used => $12,
|
||||
total_mem_from => $13*1024,
|
||||
total_mem_to => $14*1024,
|
||||
total_mem_max => $15*1024,
|
||||
total_time_used => $16 );
|
||||
}
|
||||
return %elements;
|
||||
}
|
||||
|
||||
my $record='';
|
||||
|
||||
# Print config information to munin server
|
||||
if ( $ARGV[0] and $ARGV[0] eq "config" ) {
|
||||
print "graph_title $title\n";
|
||||
print "graph_vlabel Bytes Memory\n";
|
||||
print "graph_category Java\n";
|
||||
print "graph_args --lower-limit 0\n";
|
||||
print "graph_info Show heap memory usage of JVM\n";
|
||||
print "graph_order defnew_max tenured_max tenured_start tenured_end defnew_start defnew_end totalheap totalheapmax\n";
|
||||
print "defnew_max.label DefNew max\n";
|
||||
print "defnew_max.draw AREA\n";
|
||||
print "tenured_max.label Tenured max\n";
|
||||
print "tenured_max.draw STACK\n";
|
||||
print "tenured_max.info DefNew max and Tenured max are stacked to show the total heap memory usage\n";
|
||||
print "tenured_start.label Tenured start\n";
|
||||
print "tenured_start.info Tenured (long term) memory used at start of GC\n";
|
||||
print "tenured_end.label Tenured end\n";
|
||||
print "tenured_end.info Tenured (long term) memory used at end of GC\n";
|
||||
print "defnew_start.label DefNew start\n";
|
||||
print "defnew_start.info Short term memory used by objects at start of GC\n";
|
||||
print "defnew_end.label DefNew end\n";
|
||||
print "defnew_end.info Short term memory claimed by objects that survived the GC\n";
|
||||
print "totalheapmax.label Maximum total heap\n";
|
||||
print "totalheapmax.info Maximum used total heap last 5 minutes\n";
|
||||
print "totalheaptomax.label Total heap end\n";
|
||||
print "totalheaptomax.info Heapsize at maximum after GC\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
# Scan through the log file and keep the last instance of a
|
||||
# Tenured record in $record.
|
||||
|
||||
my %last;
|
||||
# We can't be sure that there is a totalmemto in the log.
|
||||
my $totalmemto_atmax = 0;
|
||||
my $totalmemfrom_max = 0;
|
||||
|
||||
|
||||
open( FILE, "< $logfile" ) or die "Can't open $logfile: $!\n";
|
||||
|
||||
# We want to collect the highest total_mem_max in the last 5 minute period.
|
||||
seek(FILE,-4096,SEEK_END);
|
||||
my $now;
|
||||
my $lastnow = 0;
|
||||
|
||||
while (<FILE>) {
|
||||
chomp;
|
||||
if (/:/) {
|
||||
($now,undef) = split(/:/,$_,2);
|
||||
$now = $lastnow unless $now;
|
||||
}
|
||||
}
|
||||
|
||||
my $noolderthan = $now - 300;
|
||||
|
||||
# print "Latest time is: $now. 5 min ago is $noolderthan\n";
|
||||
|
||||
seek(FILE,0,SEEK_SET);
|
||||
|
||||
$lastnow = 0;
|
||||
$now=0;
|
||||
|
||||
while (<FILE>) {
|
||||
chomp;
|
||||
if (/:/) {
|
||||
($now,undef) = split(/:/,$_,2);
|
||||
$now = $lastnow unless $now;
|
||||
}
|
||||
|
||||
if (/.+Tenured.+/) {
|
||||
$record = $_;
|
||||
} elsif (/^:.+/) {
|
||||
$record .= $_;
|
||||
}
|
||||
if ($record =~ /Tenured.+secs\]$/) {
|
||||
%last = analyze_record($record);
|
||||
|
||||
#print "($now > $noolderthan and $last{total_mem_from} > $totalmemfrom_max)\n";
|
||||
|
||||
if ($now > $noolderthan and $last{total_mem_from} > $totalmemfrom_max) {
|
||||
$totalmemfrom_max = $last{total_mem_max};
|
||||
$totalmemto_atmax = $last{total_mem_to};
|
||||
# print "New larger at $now: $totalmemto_max\n";
|
||||
}
|
||||
$record = '';
|
||||
}
|
||||
$lastnow=$now;
|
||||
}
|
||||
close FILE;
|
||||
|
||||
$totalmemfrom_max=$totalmemto_atmax='U' if $totalmemfrom_max==0;
|
||||
|
||||
# Print the values to be represented in the munin graph
|
||||
print "tenured_max.value $last{total_mem_max}\n";
|
||||
print "tenured_start.value $last{total_mem_from}\n";
|
||||
print "tenured_end.value $last{total_mem_to}\n";
|
||||
|
||||
print "defnew_max.value $last{defnew_mem_max}\n";
|
||||
print "defnew_start.value $last{defnew_mem_from}\n";
|
||||
print "defnew_end.value $last{defnew_mem_to}\n";
|
||||
|
||||
print "totalheapmax.value $totalmemfrom_max\n";
|
||||
print "totalheaptomax.value $totalmemto_atmax\n";
|
130
plugins/java/jvm_sun_minorgcs
Executable file
130
plugins/java/jvm_sun_minorgcs
Executable file
|
@ -0,0 +1,130 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Sun JVM minor GC statistics. Parses a verbose log of minor GC
|
||||
# stats. Reads the log file and sums time in seconds spent on GC and
|
||||
# number of times it is performed. These numbers are saved in a state
|
||||
# file. The next time the plugin is run it only reads from the point
|
||||
# it quit the last time and increases the sums based on the lines
|
||||
# found in the last portion of the log. Thus we obtain counters. The
|
||||
# counters are reset when the log is rotated.
|
||||
|
||||
# The two numbers are graphed in _one_ graph. Where it has been used
|
||||
# until now these two numbers have been in the same order of
|
||||
# magnitude.
|
||||
|
||||
# Configuration (common with the other sun_jvm_* plugins in this family):
|
||||
# [jvm_sun_*]
|
||||
# env.logfile /var/foo/java.log (default: /var/log/munin/java.log)
|
||||
# env.graphtitle (default: "Sun Java")
|
||||
# env.grname (default: "sun-jvm". Used for state file-name)
|
||||
|
||||
# You need to configure your Sun JVM with these options:
|
||||
# -verbose:gc
|
||||
# -Xloggc:/var/log/app/jvm/gc.log
|
||||
# -XX:+PrintGCTimeStamps
|
||||
# -XX:+PrintGCDetails
|
||||
|
||||
# History:
|
||||
|
||||
# This plugin was developed by various people over some time - no logs
|
||||
# of this has been found. - In 2006 significant contributions was
|
||||
# financed by NRK (Norwegian Broadcasting Coproration) and performed
|
||||
# by Nicolai Langfeldt of Linpro AS in Oslo, Norway.
|
||||
|
||||
# $Id: $
|
||||
|
||||
use strict;
|
||||
|
||||
my $logfile = $ENV{logfile} || "/var/log/app/jvm/gc.log";
|
||||
my $grtitle = $ENV{graphtitle} || 'Sun Java';
|
||||
my $grname = $ENV{graphtitle} || 'sun-jvm';
|
||||
|
||||
my $statefile = "/var/lib/munin/plugin-state/plugin-java_sun_${grname}_minorgcs.state";
|
||||
my $pos = 0;
|
||||
my $count = 0;
|
||||
my $seconds = 0;
|
||||
my $startsize;
|
||||
my $timespent;
|
||||
my $totaltimespent=0;
|
||||
|
||||
if ( $ARGV[0] and $ARGV[0] eq "config" ) {
|
||||
print "graph_title $grtitle minor GCs pr minute\n";
|
||||
print "graph_args --base 1000 -l 0 --rigid\n";
|
||||
print "graph_scale no\n";
|
||||
print "graph_category Java\n";
|
||||
print "graph_period minute\n";
|
||||
print "gcs.label Number of GCs\n";
|
||||
print "gcs.type DERIVE\n";
|
||||
print "gcs.min 0\n";
|
||||
print "time.label Seconds spent on GC\n";
|
||||
print "time.type DERIVE\n";
|
||||
print "time.min 0\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if (-l $statefile) {
|
||||
die("$statefile is a symbolic link, refusing to touch it.");
|
||||
}
|
||||
|
||||
if (! -f $logfile) {
|
||||
print "gcs.value U\n";
|
||||
print "time.value U\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if (-f "$statefile") {
|
||||
open (IN, "$statefile") or exit 4;
|
||||
($pos,$count,$timespent) = split(/:/,<IN>);
|
||||
close IN;
|
||||
}
|
||||
|
||||
$startsize = (stat $logfile)[7];
|
||||
|
||||
if ($startsize < $pos) {
|
||||
# Log rotated
|
||||
$pos = 0;
|
||||
}
|
||||
|
||||
($pos, $count, $timespent) = parseFile ($logfile, $pos, $count, $timespent);
|
||||
|
||||
print "gcs.value $count\n";
|
||||
print "time.value ",int($timespent),"\n";
|
||||
|
||||
open (OUT, ">$statefile") or die "Could not open $statefile for reading: $!\n";
|
||||
print OUT "$pos:$count:$timespent\n";
|
||||
close OUT;
|
||||
|
||||
sub parseFile {
|
||||
my ($fname, $start, $count, $timespent) = @_;
|
||||
my @secs;
|
||||
|
||||
open (LOGFILE, $fname) or die "Could not open $fname: $!\n";
|
||||
|
||||
# Stat filehandle after open - avoids race with logrotater or
|
||||
# restart or whatever.
|
||||
|
||||
my $stop = $startsize = (stat LOGFILE)[7];
|
||||
|
||||
if ($startsize < $start) {
|
||||
# Log rotated
|
||||
$start = 0;
|
||||
}
|
||||
|
||||
seek (LOGFILE, $start, 0) or
|
||||
die "Could not seek to $start in $fname: $!\n";
|
||||
|
||||
while (tell (LOGFILE) < $stop) {
|
||||
my $line =<LOGFILE>;
|
||||
chomp ($line);
|
||||
|
||||
# Log format: 35.037: [GC 35.038: [DefNew: 166209K->11364K(174080K), 0.2106410 secs] 175274K->26037K(1721472K), 0.2107680 secs]
|
||||
if ($line =~ /\[GC.+ (\d+\.\d+) secs\]/) {
|
||||
$count++;
|
||||
$timespent += $1;
|
||||
}
|
||||
}
|
||||
close(LOGFILE);
|
||||
return($stop,$count,$timespent);
|
||||
}
|
||||
|
||||
# vim:syntax=perl
|
92
plugins/java/jvm_sun_tenuredgcs
Executable file
92
plugins/java/jvm_sun_tenuredgcs
Executable file
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/perl -w
|
||||
|
||||
# Sun JVM tenured GC statistics. Parses a verbose log of tenured GC
|
||||
# stats. Reads the entire log file and sums time in seconds spent on
|
||||
# GC and number of times it is performed. Thus we obtain counters.
|
||||
# The counters are reset when the log is rotated. (note: the minorgcs
|
||||
# plugin uses a state file, we did not make it a priority to use a
|
||||
# state file in this plugin...)
|
||||
|
||||
# The two numbers are graphed in _one_ graph. Where it has been used
|
||||
# until now these two numbers have been in the same order of
|
||||
# magnitude.
|
||||
|
||||
# Configuration (common with the other sun_jvm_* plugins in this family):
|
||||
# [jvm_sun_*]
|
||||
# env.logfile /var/foo/java.log (default: /var/log/munin/java.log)
|
||||
# env.graphtitle (default: "Sun Java")
|
||||
|
||||
# You need to configure your Sun JVM with these options:
|
||||
# -verbose:gc
|
||||
# -Xloggc:/var/log/app/jvm/gc.log
|
||||
# -XX:+PrintGCTimeStamps
|
||||
# -XX:+PrintGCDetails
|
||||
|
||||
# History:
|
||||
|
||||
# This plugin was developed by various people over some time - no logs
|
||||
# of this has been found. - In 2006 significant contributions was
|
||||
# financed by NRK (Norwegian Broadcasting Coproration) and performed
|
||||
# by Nicolai Langfeldt of Linpro AS in Oslo, Norway.
|
||||
|
||||
# $Id: $
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# Full path to jvm log file
|
||||
my $logfile = $ENV{logfile} || "/var/log/app/jvm/gc.log";
|
||||
my $grtitle = $ENV{graphtitle} || 'Sun Java';
|
||||
|
||||
# Title that appears on munin graph
|
||||
my $title = "$grtitle tenured GCs pr second";
|
||||
|
||||
# Extended information that appears below munin graph
|
||||
my $info = "Amount is the number of Tenured GC pr. second.\nSeconds spent is the total time spent on those Tenured GCs.";
|
||||
|
||||
my $record = "";
|
||||
my %elements;
|
||||
|
||||
# Print config information to munin server
|
||||
if ( $ARGV[0] and $ARGV[0] eq "config" ) {
|
||||
print "graph_title $grtitle tenured GCs pr minute\n";
|
||||
print "graph_period minute\n";
|
||||
print "graph_category Java\n";
|
||||
print "graph_args --lower-limit 0\n";
|
||||
print "graph_info $info\n";
|
||||
print "activity.label Number of GCs\n";
|
||||
print "activity.type DERIVE\n";
|
||||
print "activity.min 0\n";
|
||||
print "time.label Seconds spent on GCs\n";
|
||||
print "time.type DERIVE\n";
|
||||
print "time.min 0\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
# Scan through the log file and keep the last instance of a
|
||||
# Tenured record in $record.
|
||||
open( FILE, "< $logfile" ) or die "Can't open $logfile : $!";
|
||||
my $counter = 0;
|
||||
my $record_time_spent;
|
||||
my $time_spent;
|
||||
while (<FILE>) {
|
||||
chomp;
|
||||
if (m/.+Tenured.+/) {
|
||||
$record = $_;
|
||||
} elsif (m/^:.+/) {
|
||||
$record .= $_;
|
||||
}
|
||||
if ( $record =~ m/(\d+)\..+Tenured.+(\d+\.\d+) secs\]/ ) {
|
||||
# print "Record: $record\n";
|
||||
$record_time_spent = $2;
|
||||
# print "Time spent: ",$record_time_spent,"\n";
|
||||
|
||||
$counter++;
|
||||
$time_spent += $record_time_spent;
|
||||
}
|
||||
$record = "";
|
||||
}
|
||||
close FILE;
|
||||
|
||||
print "activity.value $counter\n";
|
||||
print "time.value ",int($time_spent),"\n";
|
Loading…
Add table
Add a link
Reference in a new issue