Skip to content

Commit

Permalink
add mbeans for socketIO and unclosed sockets
Browse files Browse the repository at this point in the history
  • Loading branch information
newbrough committed Apr 13, 2016
1 parent feeea56 commit 54c526b
Show file tree
Hide file tree
Showing 7 changed files with 274 additions and 59 deletions.
75 changes: 52 additions & 23 deletions gumshoe-probes/src/main/java/com/dell/gumshoe/Probe.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import com.dell.gumshoe.socket.SocketMatcher;
import com.dell.gumshoe.socket.SocketMatcherSeries;
import com.dell.gumshoe.socket.SubnetAddress;
import com.dell.gumshoe.socket.io.SocketIODetailAdder;
import com.dell.gumshoe.socket.io.SocketIOAccumulator;
import com.dell.gumshoe.socket.io.SocketIODetailAdder;
import com.dell.gumshoe.socket.io.SocketIOMBean;
import com.dell.gumshoe.socket.io.SocketIOMBeanImpl;
import com.dell.gumshoe.socket.io.SocketIOMonitor;
import com.dell.gumshoe.socket.unclosed.SocketCloseMBeanImpl;
import com.dell.gumshoe.socket.unclosed.SocketCloseMonitor;
import com.dell.gumshoe.socket.unclosed.SocketCloseMonitorMBean;
import com.dell.gumshoe.socket.unclosed.UnclosedStats;
import com.dell.gumshoe.stack.Filter;
import com.dell.gumshoe.stack.Filter.Builder;
Expand Down Expand Up @@ -100,7 +104,7 @@ public void setOutput(String key, PrintStream value) {
namedOutput.put(key, value);
}

private synchronized Timer getTimer() {
public synchronized Timer getTimer() {
if(timer==null) {
timer = new Timer(true);
}
Expand Down Expand Up @@ -234,10 +238,10 @@ public SocketCloseMonitor initializeSocketCloseMonitor(Properties p) throws Exce
final boolean periodicReportEnabled = periodicFrequency!=null;
final boolean reportingEnabled = periodicReportEnabled || shutdownReportEnabled;

// by default, jmx enabled if reporting it (but can override w/property)
final boolean jmxEnabled = isTrue(p, "gumshoe.socket-unclosed.mbean", reportingEnabled);
final String mbeanName = jmxEnabled ?
getMBeanName(p, "gumshoe.socket-unclosed.mbean.name", SocketCloseMonitor.class) : null;
// jmx enabled if explicit name, explicit property, or some reporting enabled
final String mbeanName = getMBeanName(p, "gumshoe.socket-unclosed.mbean.name", SocketCloseMonitor.class);
final boolean jmxEnabled = p.containsKey("gumshoe.socket-unclosed.mbean.name")
|| isTrue(p, "gumshoe.socket-unclosed.mbean", reportingEnabled);

// by default, enabled monitor only if reporting it or enabled mbean (but can override w/property)
final boolean enabled = isTrue(p, "gumshoe.socket-unclosed.enabled", reportingEnabled || jmxEnabled);
Expand All @@ -250,7 +254,7 @@ public SocketCloseMonitor initializeSocketCloseMonitor(Properties p) throws Exce

final PrintStream out = getOutput(p, "gumshoe.socket-unclosed.output", System.out);
return initializeSocketCloseMonitor(shutdownReportEnabled, periodicFrequency, minAge, clearCount,
stackFilter, mbeanName, out);
stackFilter, jmxEnabled ? mbeanName : null, out);
}

public SocketCloseMonitor initializeSocketCloseMonitor(boolean shutdownReportEnabled, Long reportPeriod, final long minAge, int clearCount,
Expand All @@ -260,26 +264,31 @@ public SocketCloseMonitor initializeSocketCloseMonitor(boolean shutdownReportEna
closeMonitor = new SocketCloseMonitor(minAge, filter);
closeMonitor.setClearClosedSocketsInterval(clearCount);

closeMonitor.initializeProbe();

// if(mbeanName!=null) {
// installMBean(mbeanName, closeMonitor, SocketCloseMonitorMBean.class);
// }

closeReporter = new ValueReporter(UNCLOSED_SOCKET_LABEL, closeMonitor);
if(shutdownReportEnabled) {
addShutdownHook(closeReporter);
}
if(out!=null) {
closeReporter.addStreamReporter(out);
}

if(shutdownReportEnabled) {
addShutdownHook(closeReporter.getShutdownHook());
}

if(reportPeriod!=null) {
getTimer().scheduleAtFixedRate(closeReporter, reportPeriod, reportPeriod);
closeReporter.scheduleReportTimer(getTimer(), reportPeriod);
}

if(mbeanName!=null) {
final SocketCloseMonitorMBean mbean = new SocketCloseMBeanImpl(this);
installMBean(mbeanName, mbean, SocketCloseMonitorMBean.class);
}

closeMonitor.initializeProbe();
return closeMonitor;
}

public SocketCloseMonitor getUnclosedMonitor() {
return closeMonitor;
}
public ValueReporter<UnclosedStats> getUnclosedReporter() {
return closeReporter;
}
Expand All @@ -291,7 +300,12 @@ public SocketIOMonitor initializeIOMonitor(Properties p) throws Exception {
final Long periodicFrequency = getNumber(p, "gumshoe.socket-io.period");
final boolean periodicReportEnabled = periodicFrequency!=null;
final boolean reportEnabled = shutdownReportEnabled || periodicReportEnabled;
final boolean jmxEnabled = isTrue(p, "gumshoe.socket-io.mbean", reportEnabled);

// jmx enabled if explicit name, explicit property, or some reporting enabled
final String mbeanName = getMBeanName(p, "gumshoe.socket-io.mbean.name", SocketIOMonitor.class);
final boolean jmxEnabled = p.containsKey("gumshoe.socket-io.mbean.name")
|| isTrue(p, "gumshoe.socket-io.mbean", reportEnabled);

final boolean enabled = isTrue(p, "gumshoe.socket-io.enabled", reportEnabled || jmxEnabled);
if( ! enabled) { return null; }

Expand All @@ -303,7 +317,7 @@ public SocketIOMonitor initializeIOMonitor(Properties p) throws Exception {

final PrintStream out = getOutput(p, "gumshoe.socket-io.output", System.out);

return initializeIOMonitor(shutdownReportEnabled, periodicFrequency, socketFilter, stackFilter, out);
return initializeIOMonitor(shutdownReportEnabled, periodicFrequency, jmxEnabled?mbeanName:null, socketFilter, stackFilter, out);
}

/** create stack filter for socket I/O
Expand Down Expand Up @@ -348,7 +362,7 @@ private StackFilter initializeStackFilter(String prefix, Properties p) {
return builder.build();
}

public SocketIOMonitor initializeIOMonitor(boolean shutdownReportEnabled, Long periodicFrequency, SocketMatcher socketFilter, StackFilter stackFilter, final PrintStream out) throws Exception {
public SocketIOMonitor initializeIOMonitor(boolean shutdownReportEnabled, Long periodicFrequency, String mbeanName, SocketMatcher socketFilter, StackFilter stackFilter, final PrintStream out) throws Exception {
if(ioMonitor!=null) throw new IllegalStateException("monitor is already installed");

ioMonitor = new SocketIOMonitor(socketFilter);
Expand All @@ -358,15 +372,20 @@ public SocketIOMonitor initializeIOMonitor(boolean shutdownReportEnabled, Long p

ioReporter = new ValueReporter(SOCKET_IO_LABEL, ioAccumulator);
if(shutdownReportEnabled) {
addShutdownHook(ioReporter);
addShutdownHook(ioReporter.getShutdownHook());
}
if(periodicFrequency!=null) {
getTimer().scheduleAtFixedRate(ioReporter, periodicFrequency, periodicFrequency);
ioReporter.scheduleReportTimer(getTimer(), periodicFrequency);
}
if(out!=null) {
ioReporter.addStreamReporter(out);
}

if(mbeanName!=null) {
final SocketIOMBean mbean = new SocketIOMBeanImpl(this);
installMBean(mbeanName, mbean, SocketIOMBean.class);
}

ioMonitor.initializeProbe();
return ioMonitor;
}
Expand All @@ -385,10 +404,20 @@ public ValueReporter<SocketIODetailAdder> getIOReporter() {

/////

private void addShutdownHook(Runnable task) {
public void addShutdownHook(Runnable task) {
if(shutdownHooks.contains(task)) { throw new IllegalStateException("shutdown hook already enabled: " + task); }
shutdownHooks.add(task);
}

public boolean removeShutdownHook(Runnable task) {
if( ! shutdownHooks.contains(task)) { throw new IllegalStateException("shutdown hook was not enabled: " + task); }
return shutdownHooks.remove(task);
}

public boolean isShutdownHookEnabled(Runnable task) {
return shutdownHooks.contains(task);
}

/////

private static final OutputStream NULL_OUTPUT_STREAM = new OutputStream() { @Override public void write(int b) { } };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@


public interface SocketIOMBean {
// public String startIOMonitor(boolean shutdownReportEnabled, Long periodicFrequency, String filter) throws Exception;
// public String stopIOMonitor() throws Exception;

// public String getIOSummary();
// public void resetIO();
public void setEnabled(boolean enabled);
public boolean isEnabled();

public String getReport();
public void reset();

public void setReportingFrequency(long millis);
public long getReportingFrequency();

public void setShutdownReportEnabled(boolean enabled);
public boolean isShutdownReportEnabled();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.dell.gumshoe.socket.io;

import com.dell.gumshoe.Probe;
import com.dell.gumshoe.socket.IO.IOStats;
import com.dell.gumshoe.stack.Stack;
import com.dell.gumshoe.stats.ValueReporter;
import com.dell.gumshoe.stats.ValueReporter.StreamReporter;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Map;

public class SocketIOMBeanImpl implements SocketIOMBean {
private final Probe probe;

public SocketIOMBeanImpl(Probe probe) {
this.probe = probe;
}

@Override
public void setEnabled(boolean enabled) {
probe.getIOMonitor().setEnabled(enabled);
}

@Override
public boolean isEnabled() {
return probe.getIOMonitor().isEnabled();
}

@Override
public String getReport() {
final ByteArrayOutputStream rawOut = new ByteArrayOutputStream();
final PrintStream out = new PrintStream(rawOut);
final ValueReporter<SocketIODetailAdder>.StreamReporter streamer = probe.getIOReporter().new StreamReporter(out);
final Map<Stack,SocketIODetailAdder> values = probe.getIOAccumulator().getStats();
streamer.statsReported(values);
return rawOut.toString();
}

@Override
public void reset() {
probe.getIOAccumulator().reset();
}

@Override
public void setReportingFrequency(long millis) {
probe.getIOReporter().scheduleReportTimer(probe.getTimer(), millis);
}

@Override
public long getReportingFrequency() {
return probe.getIOReporter().getReportTimerFrequency();
}

@Override
public void setShutdownReportEnabled(boolean enabled) {
if(enabled) {
probe.addShutdownHook(probe.getIOReporter().getShutdownHook());
} else {
probe.removeShutdownHook(probe.getIOReporter().getShutdownHook());
}
}

@Override
public boolean isShutdownReportEnabled() {
return probe.isShutdownHookEnabled(probe.getIOReporter().getShutdownHook());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.dell.gumshoe.socket.unclosed;

import com.dell.gumshoe.Probe;
import com.dell.gumshoe.stack.Stack;
import com.dell.gumshoe.stats.ValueReporter;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Map;

public class SocketCloseMBeanImpl implements SocketCloseMonitorMBean {
private final Probe probe;

public SocketCloseMBeanImpl(Probe probe) {
this.probe = probe;
}

@Override public boolean isEnabled() { return probe.getUnclosedMonitor().isEnabled(); }
@Override public void setEnabled(boolean enabled) { probe.getUnclosedMonitor().setEnabled(enabled); }

@Override
public String getReport(long age) {
final ByteArrayOutputStream rawOut = new ByteArrayOutputStream();
final PrintStream out = new PrintStream(rawOut);
final ValueReporter<UnclosedStats>.StreamReporter streamer = probe.getUnclosedReporter().new StreamReporter(out);
final Map<Stack,UnclosedStats> values = probe.getUnclosedMonitor().getStats(age);
streamer.statsReported(values);
return rawOut.toString();
}

@Override
public void setReportingFrequency(long millis) {
probe.getUnclosedReporter().scheduleReportTimer(probe.getTimer(), millis);
}

@Override
public long getReportingFrequency() {
return probe.getUnclosedReporter().getReportTimerFrequency();
}

@Override
public void setClearClosedSocketsInterval(int numberOfSockets) {
probe.getUnclosedMonitor().setClearClosedSocketsInterval(numberOfSockets);
}

@Override
public int getClearClosedSocketsInterval() {
return probe.getUnclosedMonitor().getClearClosedSocketsInterval();
}

@Override
public void setShutdownReportEnabled(boolean enabled) {
if(enabled) {
probe.addShutdownHook(probe.getUnclosedReporter().getShutdownHook());
} else {
probe.removeShutdownHook(probe.getUnclosedReporter().getShutdownHook());
}
}

@Override
public boolean isShutdownReportEnabled() {
return probe.isShutdownHookEnabled(probe.getUnclosedReporter().getShutdownHook());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,20 @@ public void setFilter(StackFilter filter) {
this.filter = filter;
}

// @Override
// public boolean isEnabled() { return enabled; }
//
// @Override
// public void setEnabled(boolean enabled) {
// this.enabled = enabled;
// if( ! enabled) {
// synchronized(clearClosedLock) {
// clearClosedSockets();
// openSockets.clear();
// countByStack.clear();
// }
// }
// }
public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
if( ! enabled) {
synchronized(clearClosedLock) {
clearClosedSockets();
openSockets.clear();
countByStack.clear();
}
}
}

/////

Expand All @@ -90,6 +90,10 @@ public void setClearClosedSocketsInterval(int numberOfSockets) {
}
}

public int getClearClosedSocketsInterval() {
return clearClosedPerCount;
}

public List<SocketImplDecorator> findOpenedBefore(long cutoff) {
final List<SocketImplDecorator> out = new ArrayList<SocketImplDecorator>();
for(SocketImplDecorator value : openSockets.values()) {
Expand Down Expand Up @@ -234,7 +238,7 @@ public Map<Stack,UnclosedStats> getStats() {
return getStats(minReportingAge);
}

private Map<Stack,UnclosedStats> getStats(long minAge) {
Map<Stack,UnclosedStats> getStats(long minAge) {
final long now = System.currentTimeMillis();
final long cutoff = now - minAge;
final List<SocketImplDecorator> unclosed = findOpenedBefore(cutoff);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,10 @@ public interface SocketCloseMonitorMBean {
public void setEnabled(boolean enabled);
public boolean isEnabled();
public String getReport(long age);
public void setReportingFrequency(long millis);
public long getReportingFrequency();
public void setClearClosedSocketsInterval(int numberOfSockets);
public int getClearClosedSocketsInterval();
public void setShutdownReportEnabled(boolean enabled);
public boolean isShutdownReportEnabled();
}
Loading

0 comments on commit 54c526b

Please sign in to comment.