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

Allow dynamic reconfiguring in the background. #33

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion README
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Configuration
(so that metrics from different JVMs on the same host can be
determined)

XML Configuation File
XML Configuration File

JMXetric schedules a number of "samples", that queries a list of "mbeans",
that have "attributes".
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package info.ganglia.jmxetric;

import info.ganglia.gmetric4j.gmetric.GMetric;
import org.xml.sax.InputSource;

import org.w3c.dom.Node;
import java.io.*;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Timer;
import java.util.TimerTask;


public class BackgroundConfigurationRefresher extends XMLConfigurationService {

private JMXetricAgent agent = null;
private final InputSource inputSource;
private final CommandLineArgs args;
private final String agentArgs;
private int pollingFrequency;
private int lastHash = -1;

public BackgroundConfigurationRefresher(String agentArgs) {
this.agentArgs = agentArgs;
this.args = new CommandLineArgs(agentArgs);
this.inputSource = new InputSource(args.getConfig());
}

public void initialize() throws Exception {
Node root = getXmlNode("/jmxetric-config/refreshconfig", inputSource);

startNewAgent();

if (isEnabled(root)) {
pollingFrequency = getPollingFrequencySeconds(root);
startBackgroundThread();
}
}

private void startNewAgent() throws Exception {
if (agent != null) {
agent.stop();
GMetric gmetric = agent.getGmetric();
if (gmetric != null) {
gmetric.close();
}
agent = null;
}

agent = new JMXetricAgent();
XMLConfigurationService.configure(agent, agentArgs);
agent.start();
lastHash = getConfigHash();
}

private boolean isEnabled(Node root) {
return selectParameterFromNode(root, "enabled", "false").toLowerCase().equals("true");
}

private int getPollingFrequencySeconds(Node root) {
return Integer.parseInt(selectParameterFromNode(root, "frequency", "5"));
}

private int getConfigHash() throws NoSuchAlgorithmException, IOException {
MessageDigest md = MessageDigest.getInstance("MD5");

File theFile = new File(args.getConfig());
InputStream is = new FileInputStream(theFile);

try {
DigestInputStream dis = new DigestInputStream(is, md);
try {
while (dis.read() != -1) {
// NOTE: This reads the entire file, that's why the while loop is blank.
}

byte[] digest = md.digest();
return new String(digest).hashCode();
} finally {
dis.close();
}
} finally {
is.close();
}
}

private void startBackgroundThread() {
TimerTask task = new TimerTask() {
@Override
public void run() {
try {
int currentHash = getConfigHash();
if (currentHash != lastHash) {
System.out.println("The file has changed. Initializing a dynamic reload for the instance.");
startNewAgent();
}
} catch (FileNotFoundException e) {
System.out.println(String.format("Could not find the config file: %s", args.getConfig()));
} catch (NoSuchAlgorithmException e) {
System.out.println("Your system does not contain the MD5 digest algorithm.");
} catch (Exception e) {
System.out.println("Unknown exception encountered.");
e.printStackTrace();
}
}
};

Timer timer = new Timer(true);
timer.scheduleAtFixedRate(task, pollingFrequency * 1000, pollingFrequency * 1000);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,9 @@ private int getPort() {
/**
* UDPAddressingMode to use for reporting
*
* @return {@link info.ganglia.gmetric4j.gmetric.UDPAddressingMode.UNICAST}
* @return {@link info.ganglia.gmetric4j.gmetric.GMetric.UDPAddressingMode.UNICAST}
* or
* {@link info.ganglia.gmetric4j.gmetric.UDPAddressingMode.MULTICAST}
* {@link info.ganglia.gmetric4j.gmetric.GMetric.UDPAddressingMode.MULTICAST}
*/
private UDPAddressingMode getAddressingMode() {
String mode = getGangliaConfig(args.getMode(), ganglia, "mode",
Expand Down Expand Up @@ -206,4 +206,4 @@ String getConfigString() throws XPathExpressionException {
buf.append(" spoof=").append(spoof);
return buf.toString();
}
}
}
5 changes: 1 addition & 4 deletions src/main/java/info/ganglia/jmxetric/JMXetricAgent.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,8 @@ public static void main(String[] args) throws Exception {
*/
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println(STARTUP_NOTICE) ;
JMXetricAgent a = null ;
try {
a = new JMXetricAgent();
XMLConfigurationService.configure(a, agentArgs);
a.start();
new BackgroundConfigurationRefresher(agentArgs).initialize();
} catch ( Exception ex ) {
// log.severe("Exception starting JMXetricAgent");
ex.printStackTrace();
Expand Down
2 changes: 0 additions & 2 deletions src/test/java/info/ganglia/jmxetric/JMXetricAgentIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@


import info.ganglia.gmetric4j.gmetric.GMetricResult;
import info.ganglia.jmxetric.JMXetricAgent;
import info.ganglia.jmxetric.XMLConfigurationService;

import java.lang.management.ManagementFactory;

Expand Down
12 changes: 8 additions & 4 deletions src/test/resources/jmxetric_test.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE jmxetric-config [
<!ELEMENT jmxetric-config (sample|ganglia|jvm)*>
<!ELEMENT jmxetric-config (sample|ganglia|jvm|refreshconfig)*>
<!ELEMENT sample (mbean)*>
<!ATTLIST sample delay CDATA #REQUIRED>
<!ATTLIST sample initialdelay CDATA "0">
Expand Down Expand Up @@ -28,6 +28,9 @@
<!ATTLIST ganglia port CDATA #REQUIRED>
<!ATTLIST ganglia mode CDATA #REQUIRED>
<!ATTLIST ganglia wireformat31x CDATA #REQUIRED>
<!ELEMENT refreshconfig EMPTY>
<!ATTLIST refreshconfig enabled CDATA #REQUIRED>
<!ATTLIST refreshconfig frequency CDATA #REQUIRED>
<!ELEMENT jvm EMPTY>
<!ATTLIST jvm process CDATA "">
]>
Expand Down Expand Up @@ -74,11 +77,12 @@
<attribute name="DaemonThreadCount" type="int16" />
</mbean>

<mbean name="java.lang:type=OperatingSystem" pname="OS" >
<attribute name="ProcessCpuTime" type="int32" slope="positive"/>
</mbean>
<mbean name="java.lang:type=OperatingSystem" pname="OS" >
<attribute name="ProcessCpuTime" type="int32" slope="positive"/>
</mbean>

</sample>
<ganglia hostname="localhost" port="8649" mode="multicast" wireformat31x="true" />
<refreshconfig enabled="true" frequency="15" />
</jmxetric-config>