From 1293615aeae4770bc74cb3e6c873440f8aaf65bb Mon Sep 17 00:00:00 2001 From: Jonathan Newbrough Date: Mon, 9 May 2016 11:07:25 -0700 Subject: [PATCH 1/2] move agent into probe --- bin/inspector | 121 ++++++++++++------ gumshoe-hooks/.gitignore | 1 - gumshoe-hooks/README.rst | 54 -------- gumshoe-hooks/pom.xml | 52 -------- gumshoe-hooks/src/test/resources/.keep | 0 gumshoe-probes/jar/META-INF/MANIFEST.MF | 1 - gumshoe-probes/jar/agent.jar | Bin 1706 -> 0 bytes .../com/dell/gumshoe/agent/ProbeLoader.class | Bin 1482 -> 0 bytes gumshoe-probes/pom.xml | 60 ++++++++- .../main/java/com/dell/gumshoe}/Agent.java | 34 ++++- .../java/com/dell/gumshoe/ProbeManager.java | 30 ++--- .../com/dell/gumshoe/hook/IoTraceAdapter.java | 0 .../com/dell/gumshoe/hook/IoTraceHandler.java | 0 .../dell/gumshoe/hook/IoTraceListener.java | 0 .../dell/gumshoe/hook/IoTraceMultiplexer.java | 0 .../java/com/dell/gumshoe/io/IOProbe.java | 4 + .../com/dell/gumshoe/util/Configuration.java | 67 ++++++---- .../java/com/dell/gumshoe/util/Output.java | 6 + .../src/main/java/sun/misc/IoTrace.java | 0 gumshoe-tools/pom.xml | 5 - .../java/com/dell/gumshoe/inspector/Main.java | 7 +- pom.xml | 1 - 22 files changed, 233 insertions(+), 210 deletions(-) delete mode 100644 gumshoe-hooks/.gitignore delete mode 100644 gumshoe-hooks/README.rst delete mode 100644 gumshoe-hooks/pom.xml delete mode 100644 gumshoe-hooks/src/test/resources/.keep delete mode 100644 gumshoe-probes/jar/META-INF/MANIFEST.MF delete mode 100644 gumshoe-probes/jar/agent.jar delete mode 100644 gumshoe-probes/jar/com/dell/gumshoe/agent/ProbeLoader.class rename {gumshoe-hooks/src/main/java/com/dell/gumshoe/hook => gumshoe-probes/src/main/java/com/dell/gumshoe}/Agent.java (72%) rename {gumshoe-hooks => gumshoe-probes}/src/main/java/com/dell/gumshoe/hook/IoTraceAdapter.java (100%) rename {gumshoe-hooks => gumshoe-probes}/src/main/java/com/dell/gumshoe/hook/IoTraceHandler.java (100%) rename {gumshoe-hooks => gumshoe-probes}/src/main/java/com/dell/gumshoe/hook/IoTraceListener.java (100%) rename {gumshoe-hooks => gumshoe-probes}/src/main/java/com/dell/gumshoe/hook/IoTraceMultiplexer.java (100%) rename {gumshoe-hooks => gumshoe-probes}/src/main/java/sun/misc/IoTrace.java (100%) diff --git a/bin/inspector b/bin/inspector index c7f1a68..b4cfed4 100755 --- a/bin/inspector +++ b/bin/inspector @@ -25,38 +25,60 @@ fi period=300000 # 5min ## add args for probes -opts="-Xmx1g" -needhook=false +needagent=false +needprobe=false while [ $# -gt 0 ] do case "$1" in - ## by default, probe is not enabled unless there is some other "main" to trace - ## using this option, investigator can monitor stats on itself (demo purposes?) - -force) - opts="$opts -Dgumshoe.probe.enabled=true " - ;; -cpu) - opts="$opts -Dgumshoe.cpu-usage.period=$period " - opts="$opts -Dgumshoe.cpu-usage.sample=5000" - opts="$opts -Dgumshoe.cpu-usage.filter.none=true" + gumshoe_opts="$gumshoe_opts -Dgumshoe.cpu-usage.period=$period " + gumshoe_opts="$gumshoe_opts -Dgumshoe.cpu-usage.sample=5000" + gumshoe_opts="$gumshoe_opts -Dgumshoe.cpu-usage.filter.none=true" + needprobe=true ;; -file-io) - opts="$opts -Dgumshoe.file-io.period=$period" - opts="$opts -Dgumshoe.file-io.filter.none=true" - needhook=true + gumshoe_opts="$gumshoe_opts -Dgumshoe.file-io.period=$period" + gumshoe_opts="$gumshoe_opts -Dgumshoe.file-io.filter.none=true" + needagent=true + needprobe=true ;; -socket-io) - opts="$opts -Dgumshoe.socket-io.period=$period" - opts="$opts -Dgumshoe.socket-io.filter.none=true" - needhook=true + gumshoe_opts="$gumshoe_opts -Dgumshoe.socket-io.period=$period" + gumshoe_opts="$gumshoe_opts -Dgumshoe.socket-io.filter.none=true" + needagent=true + needprobe=true ;; -datagram-io) - opts="$opts -Dgumshoe.datagram-io.period=$period" - opts="$opts -Dgumshoe.datagram-io.filter.none=true" + gumshoe_opts="$gumshoe_opts -Dgumshoe.datagram-io.period=$period" + gumshoe_opts="$gumshoe_opts -Dgumshoe.datagram-io.filter.none=true" + needprobe=true ;; -unclosed) - opts="$opts -Dgumshoe.socket-unclosed.period=$period" - opts="$opts -Dgumshoe.socket-unclosed.filter.none=true" + gumshoe_opts="$gumshoe_opts -Dgumshoe.socket-unclosed.period=$period" + gumshoe_opts="$gumshoe_opts -Dgumshoe.socket-unclosed.filter.none=true" + needprobe=true + ;; + -help) + cat << HELPTEXT +Inspector for gumshoe + +Usage: $0 [options...] [target-java-main [target-java-args...]] + +Options: + -help Print this message + -cpu Install cpu probe + -file-io Install file I/O probe + -socket-io Install file I/O probe + -datagram-io Install datagram I/O probe + -unclosed Install unclosed socket probe + +Any other options are passed to the JRE. + +HELPTEXT + exit + ;; + -*) + user_opts="$user_opts $1" ;; *) break @@ -66,28 +88,47 @@ do shift done -if $needhook +# by default inspector doesn't usually watch itself, +# so probes are only installed if there is a target. +# override if probe was requested... +if $needprobe && [ $# -eq 0 ] then - hookdir="$GUMSHOE_HOME/gumshoe-hooks/target" - hookcount="`ls $hookdir | grep -c '^gumshoe-hooks-*.jar'`" - case $hookcount in - 0) - echo ERROR: gumshoe hook jar not found in $hookdir 1>&2 - exit 1 - ;; - 1) - ## file and socket I/O probes need the sun.misc.SocketIo hook - hookfile="`ls $hookdir | grep '^gumshoe-hooks-*.jar'`" - opts="$opts -Xbootclasspath/p:$hookdir/$hookfile" - ;; - *) - ## could get fancy here, but i don't expect people to leave stray jars around - echo 'ERROR: more than one gumshoe hook jar found $hookdir !' 1>&2 - echo 'Rebuild with: mvn clean install' 1>&2 - exit 1 - ;; - esac + gumshoe_opts="$gumshoe_opts -Dgumshoe.probe.enabled=true " fi +if $needagent +then + agent="$GUMSHOE_HOME/gumshoe-probes/target/gumshoe-agent.jar" + if [ ! -f "$agent" ] + then + echo ERROR: did not find gumshoe agent $agent 1>&2 + exit 1 + fi + + gumshoe_opts="$gumshoe_opts -javaagent:$agent" +fi + +## now check if any user options override + +# if user did not specify max heap, set default +opts="$user_opts" +echo " $user_opts" | grep -- ' -Xms' > /dev/null +if [ $? -ne 0 ] +then + opts="-Xms1g $user_opts" +fi + +# for each property, if user did not specify add ours +for prop in $gumshoe_opts +do + regex=" `echo $prop | cut -d= -f1`=" + echo " $user_opts" | grep -- "$regex" > /dev/null + if [ $? -ne 0 ] + then + opts="$opts $prop" + fi +done + ## warning: can fail if orig cmdline contains quoted expressions like: java some.MainClass "first arg" second "third arg" +echo EXECUTING: java $opts -jar "$jarfile" $* java $opts -jar "$jarfile" $* diff --git a/gumshoe-hooks/.gitignore b/gumshoe-hooks/.gitignore deleted file mode 100644 index ae3c172..0000000 --- a/gumshoe-hooks/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bin/ diff --git a/gumshoe-hooks/README.rst b/gumshoe-hooks/README.rst deleted file mode 100644 index 0001773..0000000 --- a/gumshoe-hooks/README.rst +++ /dev/null @@ -1,54 +0,0 @@ - -Gumshoe Load Investigator JVM Hooks -=================================== - -Overview --------- - -Gumshoe adds a hook in the JVM to monitor socket and file I/O. The monitored JVM must be run -using the commandline: - - java -Xjavaagent:/PATH/TO/gumshoe-agent.jar ... - - -More Detail ------------ - -Gumshoe Load Investigator measures socket and file I/O using the sun.misc.IoTrace class. -The built-in implementation has several empty methods that are called before and after each I/O -operation. This package replaces this implementation with one that allows gumshoe to handle -these calls and collect statistics. Then any application that wants to receive the IoTrace callbacks -can implement an interface IoTraceListener and install it with IoTraceHandler.addTrace(). - - -Performance Note ----------------- - -The IoTrace callbacks occur before and after every read or write operation on every socket or file. -Without using gumshoe at all, there is CPU overhead from two empty method calls per I/O operation. -With them gumshoe agent installed but not collecting socket or file I/O, this increases slightly -- -the empty method is now replaced by a method with one line that calls an empty delegate method. -So even in CPU-constrained applications, the agent alone should not add much overhead. - -When monitoring is enabled, there is additional CPU and memory overhead involved in collecting -and accumulating I/O statistics. In many cases this is not an issue; when there is a -network or file I/O bottleneck, additional CPU and memory can be used without affecting -overall system performance. - -If CPU or memory are an issue, overhead can be reduced in several ways: - -- Divide and conquer: use fewer probes - - Collect file I/O in one pass, than and network I/O at a different time (instead of collecting both at once). - -- Divide and conquer: limit targets collected - - Select by IP address or directory to collect less information at a time. For example, collect network data - from your LAN in one pass, then collect samples from outside your LAN in another pass. - -- Reduce clutter: use stack filters - - Stack filters can reduce the size of the stacks collected significantly and make it much easier to - spot the parts of code resulting in the I/O measured. Stack filters cause some additional CPU overhead - when each sample is collected, but can reduce memory significantly. - \ No newline at end of file diff --git a/gumshoe-hooks/pom.xml b/gumshoe-hooks/pom.xml deleted file mode 100644 index 62cd81f..0000000 --- a/gumshoe-hooks/pom.xml +++ /dev/null @@ -1,52 +0,0 @@ - - 4.0.0 - - gumshoe-hooks - - gumshoe JVM hook for collecting statistics - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.3 - - 1.7 - 1.7 - - - - org.apache.maven.plugins - maven-assembly-plugin - - - - attached - - package - - - jar-with-dependencies - - - - com.dell.gumshoe.hook.Agent - true - gumshoe-agent.jar - - - gumshoe-agent - false - - - - - - - - com.dell - 0.1.0-SNAPSHOT - Gumshoe JVM Hooks - diff --git a/gumshoe-hooks/src/test/resources/.keep b/gumshoe-hooks/src/test/resources/.keep deleted file mode 100644 index e69de29..0000000 diff --git a/gumshoe-probes/jar/META-INF/MANIFEST.MF b/gumshoe-probes/jar/META-INF/MANIFEST.MF deleted file mode 100644 index 6025b13..0000000 --- a/gumshoe-probes/jar/META-INF/MANIFEST.MF +++ /dev/null @@ -1 +0,0 @@ -Premain-Class: com.dell.gumshoe.agent.ProbeLoader diff --git a/gumshoe-probes/jar/agent.jar b/gumshoe-probes/jar/agent.jar deleted file mode 100644 index 7da155eb7db8db591f836f6ef0af1c6a3d9b069b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1706 zcmWIWW@Zs#;Nak3cpb3Bg8>O}GO#fCx`sIFdiuHP|2xINz|0Wf&CUT*!30$nfK#&w zPz7AGucM!*n`>~0p0Atesf~Px6a?5F%xx)8xYFo7SIYWSRn}`O;`h#>+0^l%?8W(Z^%9vodfm70)>tp8*RjuK=l@^#X1NAhgvuLj zH`^J?<@&_u_UQ?d(BTKkb_UTT>qU9bWS-CgB;AozyS0_voES| zS%9+1`MLVIRd7O8q@?ELASpYJ7HopZ%F;`7i!<_5k(A#;Q!b88d188MUI|zeBx=w# zY2eXRl%JI9lb@K9TBMhplUQ8b8rwPH(OFVi8>UVbTedPY@<))x zxsdsKr+Kd@OurdB>zDJ_opuSq#(x{?LdxDbow}W3aHsfv@%hSg#pi4fufKo4o@s`= zSyP?LVGl>{hiNR^3#?mya=d%6F6NzQisQi~mP8fj9r|yXSu-=IKlv1Ja8r|L+k;7o zQtynK?G1|$2t;iE)TB7e&}U?u@*!XUwis%cW&IbUrQ5W4l1**{$jv0v6p|BhPPy2lc`nu+OD_9vIsNy7db*H+G0IqBhxmAcvYpIJSv zU6sUrKE%e|%_?{DvumraX}Mioz3lu$Rl)Bas{4e(H#Wx}idI(HxBL-noRQBQdj?;g z-8+>RUbf~feIv8=?qS|;4xY-3}$4M`y|WMe&JWPuQRZ$-okguQ~C6Xva@o{wF`Usowu-M zE3{>XzWyy3qab}uL+@I1_{rPq8`pn0`X`j-9EZ}q)+T{k)sqEh1*aQ4Tgma*Xq|ws zM7ZE`YtQeJjOViruYKh`s5OP>dD-CGAzt z|D=wb5S`MHIIXTY?xguYaIq9U<7CKVV7YXP6_m>vnM4>+OEp-L1uE500lb(3m2v1= zkqZw{nT7ziKqg!(QV9n#fr|lmA%igC9gqnra&YSa6*>qYzzER+ErJl*uoXfGZRW_@ z5JeI~J9_y7DwGf)4V!jY5rqh8kRiyi04k&qU^X5@(2J}9Z&o&tPIe$X0MvH{9AyAx CI5QFe diff --git a/gumshoe-probes/jar/com/dell/gumshoe/agent/ProbeLoader.class b/gumshoe-probes/jar/com/dell/gumshoe/agent/ProbeLoader.class deleted file mode 100644 index b227ed8b5896e8392e2b2edeb99f391cd301d826..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1482 zcmah}ZBx@g5Pq<wB6hc@sq~2v|UfiV9i;0YTC7qGgy-KON~=f^E`CQb+%ge%24g z(HVb$KT6z73ZxxI+UZ^H+1+QK+uiif-=Dt$%p#veH>MMqfgZ>0B<|pD9J5K>!+o_p zP{VMb%!Uxtay_S7Rty`bkHRx;E9+|%PLZ;vLJ@Ti(yw9} z#zVIMu#tZts6X>A6j5hWxq8mQ8QP4JaNXcy3567y8r&wd?_UoHI5N_J_gyYEq z(P~)7Gm3Sq)=b%SjhPL5*Aa%~c&=dsFEqSFPC0Fo=H~jZRLv5#Nrj8DO#8&DFH30+ zTi7PNIYQw(8eZWw!^p)0(7>?0e<%&=Q{NeBsB%Uw9BESlZ-wzEZrVHi6vrg;J=OGi<94R;#M zOf-=xvY{pjix~i~eEM zCklGi&_io4opjn6?Jbi>VBhE=f<9VX0}%c6tks_faEVR{4B|2&DtMW^BMSSDNGe)G z?2I7k8#v6KJP+${junit.version} test - - com.dell - gumshoe-hooks - 0.1.0-SNAPSHOT - - + + + com.coderplus.maven.plugins + copy-rename-maven-plugin + 1.0.1 + + + rename-file + compile + + rename + + + ${project.build.outputDirectory}/sun/misc/IoTrace.class + ${project.build.outputDirectory}/sun.misc.IoTrace.class + + + + + org.apache.maven.plugins maven-compiler-plugin 3.3 @@ -44,6 +59,39 @@ + + org.apache.maven.plugins + maven-assembly-plugin + + + + attached + + package + + + jar-with-dependencies + + + + com.dell.gumshoe.Agent + true + gumshoe-agent.jar + + + gumshoe-agent + false + + + + target/classes/sun/misc/IoTrace.class + sun.misc.IoTrace.class + + + + + + diff --git a/gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/Agent.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/Agent.java similarity index 72% rename from gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/Agent.java rename to gumshoe-probes/src/main/java/com/dell/gumshoe/Agent.java index e72de08..6260144 100644 --- a/gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/Agent.java +++ b/gumshoe-probes/src/main/java/com/dell/gumshoe/Agent.java @@ -1,8 +1,9 @@ -package com.dell.gumshoe.hook; +package com.dell.gumshoe; import sun.misc.IoTrace; import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -15,10 +16,24 @@ /** install our version of IoTrace to capture socket and file I/O activity */ public class Agent { - private static final String CLASS_FILENAME = "sun/misc/IoTrace.class"; + private static final String CLASS_FILENAME = "/sun.misc.IoTrace.class"; + private static boolean WAS_INSTALLED = false; public static void premain(String args, Instrumentation inst) throws Exception { - final byte[] alternate = getAlternate(); + final ProbeManager probeManager = ProbeManager.getInstance(); + probeManager.initialize(); + if(probeManager.isUsingIoTrace()) { + new Agent().installIoTraceHook(inst); + } + WAS_INSTALLED = true; + } + + public static boolean isAgentInstalled() { + return WAS_INSTALLED; + } + + private void installIoTraceHook(Instrumentation inst) throws IOException { + final byte[] alternate = getAlternateBytecode(); if(alternate==null) { System.out.println("GUMSHOE ERROR: failed to locate IoTrace hook"); return; @@ -35,7 +50,18 @@ public static void premain(String args, Instrumentation inst) throws Exception { } /** loop over classpath */ - private static byte[] getAlternate() throws IOException { + private byte[] getAlternateBytecode() throws IOException { + final InputStream in = ProbeManager.class.getResourceAsStream(CLASS_FILENAME); + final ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + final byte[] block = new byte[8192]; + int len; + while((len=in.read(block))>-1) { + buffer.write(block, 0, len); + } + return buffer.toByteArray(); + } + + private static byte[] getAlternateBytecodeOLD() throws IOException { final String[] classpath = System.getProperty("java.class.path").split(System.getProperty("path.separator")); for(String entry : classpath) { final File file = new File(entry); diff --git a/gumshoe-probes/src/main/java/com/dell/gumshoe/ProbeManager.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/ProbeManager.java index 47876e4..254324d 100644 --- a/gumshoe-probes/src/main/java/com/dell/gumshoe/ProbeManager.java +++ b/gumshoe-probes/src/main/java/com/dell/gumshoe/ProbeManager.java @@ -1,5 +1,7 @@ package com.dell.gumshoe; +import static com.dell.gumshoe.util.Output.configure; + import com.dell.gumshoe.Probe.ProbeServices; import com.dell.gumshoe.file.FileIOProbe; import com.dell.gumshoe.network.DatagramIOProbe; @@ -35,23 +37,10 @@ public class ProbeManager { public static final String CPU_USAGE_LABEL = ProcessorProbe.LABEL; public static final String DATAGRAM_IO_LABEL = DatagramIOProbe.LABEL; - public static ProbeManager MAIN_INSTANCE; - - public static void main(String... args) throws Throwable { - final String[] newArgs = new String[args.length-1]; - System.arraycopy(args, 1, newArgs, 0, args.length-1); + private static ProbeManager INSTANCE = new ProbeManager(); + public static ProbeManager getInstance() { return INSTANCE; } - MAIN_INSTANCE = new ProbeManager(); - MAIN_INSTANCE.initialize(); - - final Class mainClass = Class.forName(args[0]); - final Method mainMethod = mainClass.getDeclaredMethod("main", args.getClass()); - try { - mainMethod.invoke(mainClass, new Object[] { newArgs }); - } catch (InvocationTargetException e) { - throw e.getCause(); - } - } + private ProbeManager() { } ///// @@ -73,7 +62,10 @@ public void initialize() throws Exception { } public void initialize(Properties p) throws Exception { - initialize(new Configuration(p)); + final Configuration cfg = new Configuration(p); + initialize(cfg); + + configure(cfg); // configure logging/output } private void initialize(Configuration p) throws Exception { @@ -93,6 +85,10 @@ private void initialize(Configuration p) throws Exception { cpuProbe.initialize(p.withPrefix("cpu-usage")); } + public boolean isUsingIoTrace() { + return socketIOProbe.isAttached() || fileIOProbe.isAttached(); + } + ///// public ValueReporter getUnclosedReporter() { diff --git a/gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/IoTraceAdapter.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/hook/IoTraceAdapter.java similarity index 100% rename from gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/IoTraceAdapter.java rename to gumshoe-probes/src/main/java/com/dell/gumshoe/hook/IoTraceAdapter.java diff --git a/gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/IoTraceHandler.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/hook/IoTraceHandler.java similarity index 100% rename from gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/IoTraceHandler.java rename to gumshoe-probes/src/main/java/com/dell/gumshoe/hook/IoTraceHandler.java diff --git a/gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/IoTraceListener.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/hook/IoTraceListener.java similarity index 100% rename from gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/IoTraceListener.java rename to gumshoe-probes/src/main/java/com/dell/gumshoe/hook/IoTraceListener.java diff --git a/gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/IoTraceMultiplexer.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/hook/IoTraceMultiplexer.java similarity index 100% rename from gumshoe-hooks/src/main/java/com/dell/gumshoe/hook/IoTraceMultiplexer.java rename to gumshoe-probes/src/main/java/com/dell/gumshoe/hook/IoTraceMultiplexer.java diff --git a/gumshoe-probes/src/main/java/com/dell/gumshoe/io/IOProbe.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/io/IOProbe.java index 58c47d4..580df48 100644 --- a/gumshoe-probes/src/main/java/com/dell/gumshoe/io/IOProbe.java +++ b/gumshoe-probes/src/main/java/com/dell/gumshoe/io/IOProbe.java @@ -97,6 +97,10 @@ public boolean isEnabled() { return monitor.isEnabled(); } + public boolean isAttached() { + return monitor!=null; + } + @Override public String getReport() { final ByteArrayOutputStream rawOut = new ByteArrayOutputStream(); diff --git a/gumshoe-probes/src/main/java/com/dell/gumshoe/util/Configuration.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/util/Configuration.java index 6bcbda3..0cee290 100644 --- a/gumshoe-probes/src/main/java/com/dell/gumshoe/util/Configuration.java +++ b/gumshoe-probes/src/main/java/com/dell/gumshoe/util/Configuration.java @@ -11,6 +11,7 @@ import java.io.Reader; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Properties; public class Configuration { @@ -18,26 +19,20 @@ public class Configuration { private final Properties combinedProperties; public Configuration() throws IOException { - prefixes = new String[] { "gumshoe." }; - combinedProperties = new Properties(System.getProperties()); - initProperties(); + this(initProperties()); } public Configuration(Properties p) { prefixes = new String[] { "gumshoe." }; - combinedProperties = new Properties(System.getProperties()); + combinedProperties = new Properties(); combinedProperties.putAll(p); - } + public Configuration(Configuration delegate, String prefix) { this.prefixes = initPrefixes(prefix, delegate.prefixes); combinedProperties = delegate.combinedProperties; } - public Configuration withPrefix(String prefix) { - return new Configuration(this, prefix); - } - private static String[] initPrefixes(String newPrefix, String[] delegatePrefixes) { if(delegatePrefixes.length==1) { final String[] out = { "gumshoe."+newPrefix+".", "gumshoe." }; @@ -50,35 +45,51 @@ private static String[] initPrefixes(String newPrefix, String[] delegatePrefixes } } - public Properties initProperties() throws IOException { - final String name = System.getProperty("gumshoe.config", "gumshoe.properties"); + private static Properties initProperties() throws IOException { // don't show verbose output yet // properties determine if and where to print the messages // so collect them for now and handle in finally block final List deferredMessages = new ArrayList<>(); + + final Properties out = new Properties(); try { - try { - final Properties resourceProperties = readPropertyClasspath(name, deferredMessages); - if(resourceProperties!=null) { combinedProperties.putAll(resourceProperties); } - - final Properties fileProperties = readPropertyFile(name, deferredMessages); - if(fileProperties!=null) { combinedProperties.putAll(fileProperties); } - return combinedProperties; - } finally { - // configure output system with as many properties as we could find - configure(this); - for(String msg : deferredMessages) { - debug(msg); + final String name = System.getProperty("gumshoe.config", "gumshoe.properties"); + // first add properties file from classpath + final Properties resourceProperties = readPropertyClasspath(name, deferredMessages); + if(resourceProperties!=null) { out.putAll(resourceProperties); } + + // next add properties from filesystem + final Properties fileProperties = readPropertyFile(name, deferredMessages); + if(fileProperties!=null) { out.putAll(fileProperties); } + + // finally add cmdline properties + for(Map.Entry entry : System.getProperties().entrySet()) { + final String key = (String) entry.getKey(); + if(key.startsWith("gumshoe.")) { + out.put(key, System.getProperty(key)); } } + + configure(out); + for(String msg : deferredMessages) { + debug(msg); + } + + return out; } catch(IOException|RuntimeException e) { + // might be incomplete, but configure output system with as many properties as we could find + configure(out); + + for(String msg : deferredMessages) { + debug(msg); + } error(e, "failed to read properties"); throw e; } } - private Properties readPropertyFile(String name, List output) throws IOException { + private static Properties readPropertyFile(String name, List output) throws IOException { final File file = new File(name); if( ! file.isFile() || ! file.canRead()) { return null; } @@ -93,8 +104,8 @@ private Properties readPropertyFile(String name, List output) throws IOE } } - private Properties readPropertyClasspath(String name, List output) throws IOException { - final InputStream in = getClass().getClassLoader().getResourceAsStream(name); + private static Properties readPropertyClasspath(String name, List output) throws IOException { + final InputStream in = Configuration.class.getResourceAsStream(name); if(in==null) { return null; } output.add("GUMSHOE: reading configuration resource"); @@ -107,6 +118,10 @@ private Properties readPropertyClasspath(String name, List output) throw } } + public Configuration withPrefix(String prefix) { + return new Configuration(this, prefix); + } + ///// public String getProperty(String key) { diff --git a/gumshoe-probes/src/main/java/com/dell/gumshoe/util/Output.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/util/Output.java index 36ffb92..6cb7cd5 100644 --- a/gumshoe-probes/src/main/java/com/dell/gumshoe/util/Output.java +++ b/gumshoe-probes/src/main/java/com/dell/gumshoe/util/Output.java @@ -1,5 +1,7 @@ package com.dell.gumshoe.util; +import java.util.Properties; + public class Output { private static boolean verbose; @@ -8,6 +10,10 @@ public class Output { public static void configure(Configuration config) { setVerbose(config.isTrue("gumshoe.verbose", false)); } + public static void configure(Properties p) { + setVerbose(Boolean.valueOf(p.getProperty("gumshoe.verbose", "false"))); + } + ///// public static void print(String before, String... message) { diff --git a/gumshoe-hooks/src/main/java/sun/misc/IoTrace.java b/gumshoe-probes/src/main/java/sun/misc/IoTrace.java similarity index 100% rename from gumshoe-hooks/src/main/java/sun/misc/IoTrace.java rename to gumshoe-probes/src/main/java/sun/misc/IoTrace.java diff --git a/gumshoe-tools/pom.xml b/gumshoe-tools/pom.xml index 0e1faaa..32a951c 100644 --- a/gumshoe-tools/pom.xml +++ b/gumshoe-tools/pom.xml @@ -21,11 +21,6 @@ gumshoe-probes 0.1.0-SNAPSHOT - - com.dell - gumshoe-hooks - 0.1.0-SNAPSHOT - diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/Main.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/Main.java index fad97a5..3b5d58a 100644 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/Main.java +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/Main.java @@ -1,5 +1,6 @@ package com.dell.gumshoe.inspector; +import com.dell.gumshoe.Agent; import com.dell.gumshoe.ProbeManager; import javax.swing.JFrame; @@ -44,9 +45,9 @@ private static void launchGUI(boolean hasMain) throws Exception { } final boolean forceProbe = Boolean.getBoolean("gumshoe.probe.enabled"); - final boolean useProbe = forceProbe || hasMain; - final ProbeManager probe = useProbe ? new ProbeManager() : null; - if(useProbe) { probe.initialize(); } + final boolean needProbe = forceProbe || hasMain; + + final ProbeManager probe = needProbe ? ProbeManager.getInstance() : null; final JFrame frame = new JFrame("Inspector"); if( ! hasMain) { diff --git a/pom.xml b/pom.xml index a4c3e27..c13113b 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,6 @@ Gumshoe Load Investigator - gumshoe-hooks gumshoe-probes gumshoe-tools From 869bff274188717a2eb2111a55df5f2bb7455d47 Mon Sep 17 00:00:00 2001 From: Jonathan Newbrough Date: Mon, 9 May 2016 15:22:58 -0700 Subject: [PATCH 2/2] rename sample to report --- docs/filters.md | 2 +- docs/index.md | 6 +- docs/probe/event-handling.md | 29 +--- docs/probe/jmx-cpu-stats.md | 4 +- docs/probe/jmx-file-io.md | 4 +- docs/probe/jmx-socket-io.md | 4 +- docs/probe/properties-cpu-stats.md | 11 +- docs/probe/properties-datagram-io.md | 10 +- docs/probe/properties-file-io.md | 10 +- docs/probe/properties-socket-io.md | 10 +- docs/probe/properties-unclosed-socket.md | 10 +- docs/types/datagram-io.md | 52 +----- docs/types/file-io.md | 53 +----- docs/types/socket-io.md | 52 +----- .../java/com/dell/gumshoe/io/IOMonitor.java | 6 +- .../com/dell/gumshoe/socket/TestParsing.java | 8 +- .../gumshoe/inspector/FileDataParser.java | 42 ++--- .../java/com/dell/gumshoe/inspector/GUI.java | 59 +++---- .../dell/gumshoe/inspector/ReportSource.java | 11 ++ .../dell/gumshoe/inspector/SampleSource.java | 11 -- .../java/com/dell/gumshoe/inspector/Tool.java | 28 ++-- .../inspector/graph/StackGraphPanel.java | 2 +- .../gumshoe/inspector/tools/OptionEditor.java | 43 ----- .../inspector/tools/ProbeSourcePanel.java | 110 ++++++------- ...ileChooser.java => ReportFileChooser.java} | 40 ++--- .../tools/ReportSelectionListener.java | 12 ++ .../tools/SampleSelectionListener.java | 12 -- .../inspector/tools/StatisticChooser.java | 10 +- .../dell/gumshoe/tools/TestFileReader.java | 34 ++-- gumshoe-tools/unused/FileSourcePanel.java | 155 ------------------ .../unused/StatisticsSourcePanel.java | 109 ------------ 31 files changed, 234 insertions(+), 715 deletions(-) create mode 100644 gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/ReportSource.java delete mode 100644 gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/SampleSource.java rename gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/{SampleFileChooser.java => ReportFileChooser.java} (77%) create mode 100644 gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ReportSelectionListener.java delete mode 100644 gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/SampleSelectionListener.java delete mode 100644 gumshoe-tools/unused/FileSourcePanel.java delete mode 100644 gumshoe-tools/unused/StatisticsSourcePanel.java diff --git a/docs/filters.md b/docs/filters.md index d9a1d06..b786c1f 100644 --- a/docs/filters.md +++ b/docs/filters.md @@ -10,7 +10,7 @@ frames to identify exactly what is relevant to your application and the current As a side note, there are really two places where stack frames are filtered. In the probe, a loose filter can drop the most obvious candidates to reduce the memory usage and file size while collecting data. Then in the viewer a more restrictive filter can better refine the view. To start, maybe just exclude -the JDK and gumshoe classes in the probe (the default). After collecting and looking at samples from +the JDK and gumshoe classes in the probe (the default). After collecting and looking at reports from your application, you will better be able to identify other packages and classes to exclude from collection. I'll describe ONE APPROACH I've used to get good results from gumshoe. I'm sure this isn't the only way diff --git a/docs/index.md b/docs/index.md index dff96c9..43cd1f0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -24,7 +24,7 @@ Getting Started - Step by step -Collecting Samples +Generating Reports ------------------ - [About the hooks](hooks.md) @@ -32,12 +32,12 @@ Collecting Samples - [Using filters](filters.md) - [Running your program](run.md) -Viewing Samples +Viewing Reports --------------- - Running gumshoe GUI from your JVM - Running standalone GUI -- Selecting a data sample +- Selecting a data report - Navigating the graph - Graph display options - Configuring filters diff --git a/docs/probe/event-handling.md b/docs/probe/event-handling.md index dce2a9c..7976956 100644 --- a/docs/probe/event-handling.md +++ b/docs/probe/event-handling.md @@ -51,8 +51,6 @@ to improve reporting. gumshoe.datagram-io.handler.queue-size=1000 gumshoe.file-io.handler.queue-size=1000 - - The queue will fill if events are produced (individual I/O operations) faster than they are consumed. Some possible reasons: @@ -73,28 +71,5 @@ to improve reporting. Or it could be due to gumshoe stack filters. Each stack filter configured has to modify the event call stack on the same event handling thread. Complex filters (such as the recursion filter) or deep call stacks can result in more load than the - thread can handle. Relax [filters](../filters.md) (at the expense of more memory use) or increase the - event handler thread priority. - - If the event queue is full: - - - Ignore it (_really!, it isn't so bad..._) - - If the problem is intermittent, it may not affect all samples, - and data reported in those affected is still likely a representative subset of all I/O. - Total I/O values will not be accurate but the relative I/O comparisons between threads - should still provide insight into what the target application is doing to generate the I/O load. - - - Increase queue size - - If the problem is intermittent, then a larger queue can let the handler thread - catch up after load spikes. However, if load is consistently over the handler capacity, - this will just delay and not fix the problem. (Requires restart) - - - Increase handler thread priority - - Socket and file I/O events perform all filtering and accumulation functions on the - handler thread. The default is to run at Thread.MIN_PRIORITY, reflecting the decision to - risk dropping data rather than impact the target application. This can be changed to a - higher value to reduce dropping events even if it means taking some CPU time away from - the target application. + thread can handle. Relax [filters](../filters.md) (at the expense of more memory use) + or increase the number of threads or the event handler thread priority. diff --git a/docs/probe/jmx-cpu-stats.md b/docs/probe/jmx-cpu-stats.md index 7d466b2..b3d02ed 100644 --- a/docs/probe/jmx-cpu-stats.md +++ b/docs/probe/jmx-cpu-stats.md @@ -20,8 +20,8 @@ This mbean will allow you to alter these attributes: In addition these operations can be performed: getReport() Return a text report of the current contents of the collection buffer. - This will likely represent a partial sample if periodic reporting is enabled + This will likely represent a partial report if periodic reporting is enabled for the time since the start of the last reporting interval. reset() Clear the contents of the collection buffer. If periodic reporting is enabled, the next report sent to configured listeners - will not contain a full sample as this data will have been removed. \ No newline at end of file + will not contain a full report as this data will have been removed. \ No newline at end of file diff --git a/docs/probe/jmx-file-io.md b/docs/probe/jmx-file-io.md index 998436e..9f19b65 100644 --- a/docs/probe/jmx-file-io.md +++ b/docs/probe/jmx-file-io.md @@ -14,8 +14,8 @@ This mbean will allow you to alter these attributes: In addition these operations can be performed: getReport() Return a text report of the current contents of the collection buffer. - This will likely represent a partial sample if periodic reporting is enabled + This will likely represent a partial report if periodic reporting is enabled for the time since the start of the last reporting interval. reset() Clear the contents of the collection buffer. If periodic reporting is enabled, the next report sent to configured listeners - will not contain a full sample as this data will have been removed. \ No newline at end of file + will not contain a full report as this data will have been removed. \ No newline at end of file diff --git a/docs/probe/jmx-socket-io.md b/docs/probe/jmx-socket-io.md index d77e69b..0cec7a1 100644 --- a/docs/probe/jmx-socket-io.md +++ b/docs/probe/jmx-socket-io.md @@ -14,8 +14,8 @@ This mbean will allow you to alter these attributes: In addition these operations can be performed: getReport() Return a text report of the current contents of the collection buffer. - This will likely represent a partial sample if periodic reporting is enabled + This will likely represent a partial report if periodic reporting is enabled for the time since the start of the last reporting interval. reset() Clear the contents of the collection buffer. If periodic reporting is enabled, the next report sent to configured listeners - will not contain a full sample as this data will have been removed. \ No newline at end of file + will not contain a full report as this data will have been removed. \ No newline at end of file diff --git a/docs/probe/properties-cpu-stats.md b/docs/probe/properties-cpu-stats.md index fe63143..37a23d5 100644 --- a/docs/probe/properties-cpu-stats.md +++ b/docs/probe/properties-cpu-stats.md @@ -8,8 +8,8 @@ Configuration Properties Initialization can use system properties by calling Probe.initialize() or with an explicit Properties argument. - gumshoe.cpu-usage.period Data samples will be reported at regular intervals (in milliseconds) - gumshoe.cpu-usage.onshutdown If true, data samples will be reported when the JVM exits + gumshoe.cpu-usage.period Reports will be generated at regular intervals (in milliseconds) + gumshoe.cpu-usage.onshutdown If true, a report will be generated when the JVM exits gumshoe.cpu-usage.mbean If true, enable JMX control of CPU usage probe gumshoe.cpu-usage.mbean.name Override name of JMX control (default is based on fully qualified class name) @@ -18,6 +18,7 @@ Initialization can use system properties by calling Probe.initialize() or with a now but enable/disable the reporting at another time. gumshoe.cpu-usage.priority Thread priority for data collection thread (default value is Thread.MIN_PRIORITY) gumshoe.cpu-usage.sample Thread data collection rate (milliseconds, default 5000) + Generally multiple samples are accumulated into each report. gumshoe.cpu-usage.jitter Collection rate should vary randomly by this amount (milliseconds, default 0) gumshoe.cpu-usage.use-wait-times Thread contention monitoring is enabled by default on @@ -29,9 +30,9 @@ Stacks should generally be [filtered](../filters.md) reduce overhead and simplif gumshoe.cpu-usage.filter... See common filter properties [here](filter-properties.md) -Collected data samples are written to: +Collected data reports are written to: - gumshoe.cpu-usage.output=none Do not write samples (ie, when your program is - adding its own explicit Listener to receive samples) + gumshoe.cpu-usage.output=none Do not write reports (ie, when your program is + adding its own explicit Listener to receive reports) gumshoe.cpu-usage.output=stdout Write to System.out (the default) gumshoe.cpu-usage.output=file:/some/path Write to a text file. diff --git a/docs/probe/properties-datagram-io.md b/docs/probe/properties-datagram-io.md index 01497cb..83238ce 100644 --- a/docs/probe/properties-datagram-io.md +++ b/docs/probe/properties-datagram-io.md @@ -8,8 +8,8 @@ Configuration Properties Initialization can use system properties by calling Probe.initialize() or with an explicit Properties argument. - gumshoe.datagram-io.period Data samples will be reported at regular intervals (in milliseconds) - gumshoe.datagram-io.onshutdown If true, data samples will be reported when the JVM exits + gumshoe.datagram-io.period Data reports will be generated at regular intervals (in milliseconds) + gumshoe.datagram-io.onshutdown If true, a report will be generated when the JVM exits gumshoe.datagram-io.mbean If true, enable JMX control of datagram usage probe gumshoe.datagram-io.mbean.name Override name of JMX control (default is based on fully qualified class name) @@ -35,10 +35,10 @@ Stacks should generally be [filtered](../filters.md) reduce overhead and simplif gumshoe.datagram-io.filter... See common filter properties [here](filter-properties.md) -Collected data samples are written to: +Collected data reports are written to: - gumshoe.datagram-io.output=none Do not write samples (ie, when your program is - adding its own explicit Listener to receive samples) + gumshoe.datagram-io.output=none Do not write reports (ie, when your program is + adding its own explicit Listener to receive reports) gumshoe.datagram-io.output=stdout Write to System.out (the default) gumshoe.datagram-io.output=file:/some/path Write to a text file. diff --git a/docs/probe/properties-file-io.md b/docs/probe/properties-file-io.md index d48bd44..a216616 100644 --- a/docs/probe/properties-file-io.md +++ b/docs/probe/properties-file-io.md @@ -8,8 +8,8 @@ Configuration Properties Initialization can use system properties by calling Probe.initialize() or with an explicit Properties argument. - gumshoe.file-io.period Data samples will be reported at regular intervals (in milliseconds) - gumshoe.file-io.onshutdown If true, data samples will be reported when the JVM exits + gumshoe.file-io.period Data reports will be reported at regular intervals (in milliseconds) + gumshoe.file-io.onshutdown If true, data reports will be reported when the JVM exits gumshoe.file-io.mbean If true, enable JMX control of file usage probe gumshoe.file-io.mbean.name Override name of JMX control (default is based on fully qualified class name) @@ -35,9 +35,9 @@ Stacks should generally be [filtered](../filters.md) reduce overhead and simplif gumshoe.file-io.filter... See common filter properties [here](filter-properties.md) -Collected data samples are written to: +Collected data reports are written to: - gumshoe.file-io.output=none Do not write samples (ie, when your program is - adding its own explicit Listener to receive samples) + gumshoe.file-io.output=none Do not write reports (ie, when your program is + adding its own explicit Listener to receive reports) gumshoe.file-io.output=stdout Write to System.out (the default) gumshoe.file-io.output=file:/some/path Write to a text file. diff --git a/docs/probe/properties-socket-io.md b/docs/probe/properties-socket-io.md index 1ed977f..3c83dc2 100644 --- a/docs/probe/properties-socket-io.md +++ b/docs/probe/properties-socket-io.md @@ -8,8 +8,8 @@ Configuration Properties Initialization can use system properties by calling Probe.initialize() or with an explicit Properties argument. - gumshoe.socket-io.period Data samples will be reported at regular intervals (in milliseconds) - gumshoe.socket-io.onshutdown If true, data samples will be reported when the JVM exits + gumshoe.socket-io.period Data reports will be generated at regular intervals (in milliseconds) + gumshoe.socket-io.onshutdown If true, a report will be generated when the JVM exits gumshoe.socket-io.mbean If true, enable JMX control of socket usage probe gumshoe.socket-io.mbean.name Override name of JMX control (default is based on fully qualified class name) @@ -35,9 +35,9 @@ Stacks should generally be [filtered](../filters.md) reduce overhead and simplif gumshoe.socket-io.filter... See common filter properties [here](filter-properties.md) -Collected data samples are written to: +Collected data reports are written to: - gumshoe.socket-io.output=none Do not write samples (ie, when your program is - adding its own explicit Listener to receive samples) + gumshoe.socket-io.output=none Do not write reports (ie, when your program is + adding its own explicit Listener to receive reports) gumshoe.socket-io.output=stdout Write to System.out (the default) gumshoe.socket-io.output=file:/some/path Write to a text file. diff --git a/docs/probe/properties-unclosed-socket.md b/docs/probe/properties-unclosed-socket.md index 679408d..ef2d013 100644 --- a/docs/probe/properties-unclosed-socket.md +++ b/docs/probe/properties-unclosed-socket.md @@ -9,8 +9,8 @@ Configuration Properties Initialization can use system properties by calling Probe.initialize() or with an explicit Properties argument. - gumshoe.socket-unclosed.period Data samples will be reported at regular intervals (in milliseconds) - gumshoe.socket-unclosed.onshutdown If true, data samples will be reported when the JVM exits + gumshoe.socket-unclosed.period Reports will be generated at regular intervals (in milliseconds) + gumshoe.socket-unclosed.onshutdown If true, a report will be generated when the JVM exits gumshoe.socket-unclosed.mbean If true, enable JMX control of socket usage probe gumshoe.socket-unclosed.mbean.name Override name of JMX control (default is based on fully qualified class name) @@ -22,9 +22,9 @@ Stacks should generally be [filtered](../filters.md) reduce overhead and simplif gumshoe.socket-unclosed.filter... See common filter properties [here](filter-properties.md) -Collected data samples are written to: +Collected data reports are written to: - gumshoe.socket-unclosed.output=none Do not write samples (ie, when your program is - adding its own explicit Listener to receive samples) + gumshoe.socket-unclosed.output=none Do not write reports (ie, when your program is + adding its own explicit Listener to receive reports) gumshoe.socket-unclosed.output=stdout Write to System.out (the default) gumshoe.socket-unclosed.output=file:/some/path Write to a text file. diff --git a/docs/types/datagram-io.md b/docs/types/datagram-io.md index f6372d3..9b62250 100644 --- a/docs/types/datagram-io.md +++ b/docs/types/datagram-io.md @@ -8,7 +8,7 @@ For each unique call stack that performs sends or receives a datagram, gumshoe reports totals for read, write and combined: number of calls, number of bytes, and elapsed time. -Samples collected can be filtered by IP, mask and port to limit results to only certain systems or services. +Samples collected can be filtered by IP, mask and port to limit reports to only certain systems or services. Hooks ----- @@ -39,51 +39,5 @@ Limitations - While the queue capacity is exceeded, events may be dropped and a message is shown in STDOUT If this is happening occasionally during peak loads, it may not be an issue. I/O statistics are still - gathered -- it just samples fewer when the queue is full. If this is happening a lot during the loads - being tested then it can be addressed. - - The queue will fill if events are produced (individual I/O operations) faster than they are consumed. - Some possible reasons: - - - The target application is performing a lot of small network operations - - This could be an area to improve the target application. - Lots of small operations are less efficient than fewer large operations. - - Or this could just be the nature of the expected application load, - so increase the gumshoe event queue size and the handler thread priority to accommodate. - - - The JVM is CPU bound - - The event queue may back up if the target application is CPU bound. This could be - an issue in the target application itself, and you may want to look at - [processor utilization statistics](../types/cpu-stats.md) before socket I/O. - - Or it could be due to gumshoe stack filters. Each stack filter configured has to - modify the event call stack on the same event handling thread. Complex filters - (such as the recursion filter) or deep call stacks can result in more load than the - thread can handle. Relax [filters](../filters.md) (at the expense of more memory use) or increase the - event handler thread priority. - - If the event queue is full: - - - Ignore it (_really!, it isn't so bad..._) - - If the problem is intermittent, it may not affect all samples, - and data reported in those affected is still likely a representative subset of all I/O. - Total I/O values will not be accurate but the relative I/O comparisons between threads - should still provide insight into what the target application is doing to generate the I/O load. - - - Increase queue size - - If the problem is intermittent, then a larger queue can let the handler thread - catch up after load spikes. However, if load is consistently over the handler capacity, - this will just delay and not fix the problem. (Requires restart) - - - Increase handler thread priority - - Socket and file I/O events perform all filtering and accumulation functions on the - handler thread. The default is to run at Thread.MIN_PRIORITY, reflecting the decision to - risk dropping data rather than impact the target application. This can be changed to a - higher value to reduce dropping events even if it means taking some CPU time away from - the target application. + gathered -- it just samples fewer operations when the queue is full. If this is happening a lot during the loads + being tested then look at then [event handler configuration](../probes/event-handling.md). diff --git a/docs/types/file-io.md b/docs/types/file-io.md index c4eae25..2ad2e33 100644 --- a/docs/types/file-io.md +++ b/docs/types/file-io.md @@ -8,7 +8,7 @@ For each unique call stack that reads or writes file data, gumshoe reports totals for read, write and combined: number of calls, number of bytes, and elapsed time. -Samples collected can be filtered with wildcards to limit results to certain file names, directories or filesystems. +Samples collected can be filtered with wildcards to limit reports to certain file names, directories or filesystems. Hooks ----- @@ -37,51 +37,6 @@ Limitations - While the queue capacity is exceeded, events may be dropped and a message is shown in STDOUT If this is happening occasionally during peak loads, it may not be an issue. I/O statistics are still - gathered -- it just samples fewer when the queue is full. If this is happening a lot during the loads - being tested then it can be addressed. - - The queue will fill if events are produced (individual I/O operations) faster than they are consumed. - Some possible reasons: - - - The target application is performing a lot of small network operations - - This could be an area to improve the target application. - Lots of small operations are less efficient than fewer large operations. - - Or this could just be the nature of the expected application load, - so increase the gumshoe event queue size and the handler thread priority to accommodate. - - - The JVM is CPU bound - - The event queue may back up if the target application is CPU bound. This could be - an issue in the target application itself, and you may want to look at - [processor utilization statistics](../types/cpu-stats.md) before socket I/O. - - Or it could be due to gumshoe stack filters. Each stack filter configured has to - modify the event call stack on the same event handling thread. Complex filters - (such as the recursion filter) or deep call stacks can result in more load than the - thread can handle. Relax [filters](../filters.md) (at the expense of more memory use) or increase the - event handler thread priority. - - If the event queue is full: - - - Ignore it (_really!, it isn't so bad..._) - - If the problem is intermittent, it may not affect all samples, - and data reported in those affected is still likely a representative subset of all I/O. - Total I/O values will not be accurate but the relative I/O comparisons between threads - should still provide insight into what the target application is doing to generate the I/O load. - - - Increase queue size - - If the problem is intermittent, then a larger queue can let the handler thread - catch up after load spikes. However, if load is consistently over the handler capacity, - this will just delay and not fix the problem. (Requires restart) - - - Increase handler thread priority - - Socket and file I/O events perform all filtering and accumulation functions on the - handler thread. The default is to run at Thread.MIN_PRIORITY, reflecting the decision to - risk dropping data rather than impact the target application. This can be changed to a - higher value to reduce dropping events even if it means taking some CPU time away from - the target application. + gathered -- report just contain samples fewer when the queue is full. If this is happening a lot during the loads + being tested then look at then [event handler configuration](../probes/event-handling.md). + \ No newline at end of file diff --git a/docs/types/socket-io.md b/docs/types/socket-io.md index 8fa940a..8724bfd 100644 --- a/docs/types/socket-io.md +++ b/docs/types/socket-io.md @@ -7,7 +7,7 @@ Data For each unique call stack that performs I/O, gumshoe reports totals for read, write and combined: number of calls, number of bytes, and elapsed time. -Samples collected can be filtered by IP, mask and port to limit results to only certain systems or services. +Samples collected can be filtered by IP, mask and port to limit reports to only certain systems or services. Hooks ----- @@ -40,51 +40,5 @@ Limitations - While the queue capacity is exceeded, events may be dropped and a message is shown in STDOUT If this is happening occasionally during peak loads, it may not be an issue. I/O statistics are still - gathered -- it just samples fewer when the queue is full. If this is happening a lot during the loads - being tested then it can be addressed. - - The queue will fill if events are produced (individual I/O operations) faster than they are consumed. - Some possible reasons: - - - The target application is performing a lot of small network operations - - This could be an area to improve the target application. - Lots of small operations are less efficient than fewer large operations. - - Or this could just be the nature of the expected application load, - so increase the gumshoe event queue size and the handler thread priority to accommodate. - - - The JVM is CPU bound - - The event queue may back up if the target application is CPU bound. This could be - an issue in the target application itself, and you may want to look at - [processor utilization statistics](../types/cpu-stats.md) before socket I/O. - - Or it could be due to gumshoe stack filters. Each stack filter configured has to - modify the event call stack on the same event handling thread. Complex filters - (such as the recursion filter) or deep call stacks can result in more load than the - thread can handle. Relax [filters](../filters.md) (at the expense of more memory use) or increase the - event handler thread priority. - - If the event queue is full: - - - Ignore it (_really!, it isn't so bad..._) - - If the problem is intermittent, it may not affect all samples, - and data reported in those affected is still likely a representative subset of all I/O. - Total I/O values will not be accurate but the relative I/O comparisons between threads - should still provide insight into what the target application is doing to generate the I/O load. - - - Increase queue size - - If the problem is intermittent, then a larger queue can let the handler thread - catch up after load spikes. However, if load is consistently over the handler capacity, - this will just delay and not fix the problem. (Requires restart) - - - Increase handler thread priority - - Socket and file I/O events perform all filtering and accumulation functions on the - handler thread. The default is to run at Thread.MIN_PRIORITY, reflecting the decision to - risk dropping data rather than impact the target application. This can be changed to a - higher value to reduce dropping events even if it means taking some CPU time away from - the target application. + gathered -- reports just contain fewer samples when the queue is full. If this is happening a lot during the loads + being tested then look at then [event handler configuration](../probes/event-handling.md). diff --git a/gumshoe-probes/src/main/java/com/dell/gumshoe/io/IOMonitor.java b/gumshoe-probes/src/main/java/com/dell/gumshoe/io/IOMonitor.java index 9700a81..266b2be 100644 --- a/gumshoe-probes/src/main/java/com/dell/gumshoe/io/IOMonitor.java +++ b/gumshoe-probes/src/main/java/com/dell/gumshoe/io/IOMonitor.java @@ -124,14 +124,14 @@ protected void queueEvent(IOEvent operation) { } // http://stackoverflow.com/questions/6072040 - private void updateMax(int sample) { + private void updateMax(int size) { while(true) { final int currentMax = maxSize.get(); // no need to update - if (currentMax >= sample) { return; } + if (currentMax >= size) { return; } // check if another thread updated first - final boolean setSuccessful = maxSize.compareAndSet(currentMax, sample); + final boolean setSuccessful = maxSize.compareAndSet(currentMax, size); if (setSuccessful) { break; } // another thread did, start over diff --git a/gumshoe-probes/src/test/java/com/dell/gumshoe/socket/TestParsing.java b/gumshoe-probes/src/test/java/com/dell/gumshoe/socket/TestParsing.java index 84fccbb..044d8e1 100644 --- a/gumshoe-probes/src/test/java/com/dell/gumshoe/socket/TestParsing.java +++ b/gumshoe-probes/src/test/java/com/dell/gumshoe/socket/TestParsing.java @@ -44,10 +44,10 @@ public void testStackParse() { StackTraceElement copy = Stack.parseFrame(stringValue); assertEquals(orig, copy); - StackTraceElement sample = Stack.parseFrame(" at com.enstratus.task.TaskBlocker.getTaskInfo(TaskBlocker.java:40)"); - assertEquals("com.enstratus.task.TaskBlocker", sample.getClassName()); - assertEquals("getTaskInfo", sample.getMethodName()); - assertEquals(40, sample.getLineNumber()); + StackTraceElement report = Stack.parseFrame(" at com.enstratus.task.TaskBlocker.getTaskInfo(TaskBlocker.java:40)"); + assertEquals("com.enstratus.task.TaskBlocker", report.getClassName()); + assertEquals("getTaskInfo", report.getMethodName()); + assertEquals(40, report.getLineNumber()); } public void testTagParse() throws ParseException { diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/FileDataParser.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/FileDataParser.java index b4361cb..a85d064 100644 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/FileDataParser.java +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/FileDataParser.java @@ -22,16 +22,16 @@ * * 1) navigate forwards and backwards * fp = new FileParser(file); - * Map sample = fp.getNextSample(); - * Date time = fp.getSampleTime(); + * Map report = fp.getNextReport(); + * Date time = fp.getReportTime(); * fp.close(); * - * 2) parse whole file and choose sample: + * 2) parse whole file and choose report: * fp = new FileParser(file); * fp.parseFile(); - * Collection times = fp.getSampleTimes(); + * Collection times = fp.getReportTimes(); * Date time = chooseOne( times ); - * Map sample = fp.getSample(time); + * Map report = fp.Report(time); */ public class FileDataParser { private final BidirectionalMap savedPositions = new BidirectionalMap(); @@ -58,57 +58,57 @@ public void close() throws IOException { ///// - /** scan entire file to find gumshoe samples */ + /** scan entire file to find gumshoe reports */ public void parseFile() throws Exception { while(read()!=null) { } } - /** return all sample times found so far (may be incomplete if parseFile() has not been called) */ - public Collection getSampleTimes() { + /** return all report times found so far (may be incomplete if parseFile() has not been called) */ + public Collection getReportTimes() { return savedPositions.getTimes(); } - /** return sample collected at given time (may not find if parseFile() has not been called) */ - public Map getSample(Date date) throws Exception { + /** return report collected at given time (may not find if parseFile() has not been called) */ + public Map getReport(Date date) throws Exception { final Long position = savedPositions.getPosition(date); if(position==null) { lastPosition = null; return null; } raf.seek(position); - return getNextSample(); + return getNextReport(); } ///// - /** return next sample found after current position in file */ - public Map getNextSample() throws Exception { + /** return next report found after current position in file */ + public Map getNextReport() throws Exception { long positionBefore = raf.getFilePointer(); - Map sample = read(); - if(sample==null) { + Map report = read(); + if(report==null) { parsedWholeFile = true; lastPosition = null; raf.seek(0); // wrap around } else { lastPosition = savedPositions.getPositionAtOrAfter(positionBefore); } - return sample; + return report; } - /** return sample prior to current position in file */ - public Map getPreviousSample() throws Exception { + /** return report prior to current position in file */ + public Map getPreviousReport() throws Exception { lastPosition = savedPositions.getPositionBefore(lastPosition); if(lastPosition==null) { return null; } raf.seek(lastPosition); return read(); } - /** return time of last sample returned */ - public Date getSampleTime() { + /** return time of last report returned */ + public Date getReportTime() { return savedPositions.getTime(lastPosition); } - public String getSampleType() { + public String getReportType() { return typeByPosition.get(lastPosition); } private Map read() throws Exception { diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/GUI.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/GUI.java index 3605543..c128f93 100644 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/GUI.java +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/GUI.java @@ -8,8 +8,8 @@ import com.dell.gumshoe.inspector.tools.DetailPanel; import com.dell.gumshoe.inspector.tools.FilterEditor; import com.dell.gumshoe.inspector.tools.ProbeSourcePanel; -import com.dell.gumshoe.inspector.tools.SampleFileChooser; -import com.dell.gumshoe.inspector.tools.SampleSelectionListener; +import com.dell.gumshoe.inspector.tools.ReportFileChooser; +import com.dell.gumshoe.inspector.tools.ReportSelectionListener; import com.dell.gumshoe.stack.Stack; import com.dell.gumshoe.stats.StatisticAdder; @@ -25,20 +25,20 @@ /** inspector GUI components * create and connect gumshoe components */ -public class GUI extends JPanel implements GUIComponents, SampleSelectionListener { +public class GUI extends JPanel implements GUIComponents, ReportSelectionListener { private final JFrame frame; - private final SampleFileChooser fileSource; + private final ReportFileChooser fileSource; private final ProbeSourcePanel probeSource; private final FilterEditor filterEditor; private final StackGraphPanel graph; private final DetailPanel detailPanel; private final JPanel aboutPanel = new AboutPanel(); - private SampleSource currentSource; + private ReportSource currentSource; public GUI(final JFrame frame, ProbeManager probe, boolean hasMain) { this.frame = frame; - this.fileSource = new SampleFileChooser(); // FileSourcePanel(); + this.fileSource = new ReportFileChooser(); // FileSourcePanel(); fileSource.addListener(this); if(probe==null) { @@ -57,31 +57,18 @@ public GUI(final JFrame frame, ProbeManager probe, boolean hasMain) { toolbar.add(tool.getButton()); } Tool.setTargetComponents(this); - Tool.LOAD_NEXT_SAMPLE.getButton().setEnabled(false); - Tool.LOAD_PREVIOUS_SAMPLE.getButton().setEnabled(false); + Tool.LOAD_NEXT_REPORT.getButton().setEnabled(false); + Tool.LOAD_PREVIOUS_REPORT.getButton().setEnabled(false); detailPanel = new DetailPanel(); graph.addSelectionListener(detailPanel); -// detailPanel = new JPanel(); -// detailPanel.setLayout(new BorderLayout()); -// final JComponent detailField = graph.getDetailField(); -// final JScrollPane scroll = new JScrollPane(detailField); -// detailPanel.add(scroll, BorderLayout.CENTER); - filterEditor = new FilterEditor(); filterEditor.setGraph(graph); -// final JPanel graphPanel = new JPanel(); -// graphPanel.setLayout(new BorderLayout()); -// graphPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); -// graphPanel.add(graph); - final JScrollPane graphScroll = new JScrollPane(graph); graphScroll.setColumnHeaderView(new Ruler(graphScroll)); -// final RulerViewport viewport = new RulerViewport(); -// viewport.setView(graph); -// graphScroll.setViewport(viewport); + setLayout(new BorderLayout()); add(toolbar, BorderLayout.NORTH); add(graphScroll, BorderLayout.CENTER); @@ -91,7 +78,7 @@ public GUI(final JFrame frame, ProbeManager probe, boolean hasMain) { public JFrame getFrame() { return frame; } public JComponent getProbeControl() { return probeSource; } - public SampleFileChooser getFileControl() { return fileSource; } + public ReportFileChooser getFileControl() { return fileSource; } public JComponent getFilterControl() { return filterEditor; } public JComponent getStatisticControl() { return graph.getStatisticChooser(); } public JComponent getGraphControl() { return graph.getOptionEditor(); } @@ -123,45 +110,45 @@ public void zoomOut() { } @Override - public void previousSample() { + public void previousReport() { if(currentSource!=null) { - currentSource.previousSample(); + currentSource.previousReport(); } } @Override - public void nextSample() { + public void nextReport() { if(currentSource!=null) { - currentSource.nextSample(); + currentSource.nextReport(); } } ///// private void togglePrevNextButtons() { - Tool.LOAD_NEXT_SAMPLE.getButton().setEnabled(currentSource.hasNext()); - Tool.LOAD_PREVIOUS_SAMPLE.getButton().setEnabled(currentSource.hasPrevious()); + Tool.LOAD_NEXT_REPORT.getButton().setEnabled(currentSource.hasNext()); + Tool.LOAD_PREVIOUS_REPORT.getButton().setEnabled(currentSource.hasPrevious()); } @Override - public void sampleWasSelected(Object source, String time, String type, Map data) { + public void reportWasSelected(Object source, String time, String type, Map data) { // track source for prev and next buttons final boolean isProbeSource = source==probeSource; this.currentSource = isProbeSource ? probeSource : fileSource; togglePrevNextButtons(); - // show current sample in title bar - frame.setTitle("Inspector: "+ type + " data @ " + time + " from " +(isProbeSource?"probe":source)); + // show current report in title bar + frame.setTitle("Reporting "+ type + " data @ " + time + " from " +(isProbeSource?"probe":source)); - // show stat options for current sample type - graph.getStatisticChooser().sampleWasSelected(source, time, type, data); + // show stat options for current report type + graph.getStatisticChooser().reportWasSelected(source, time, type, data); // display graph graph.updateModel(data); } - // when source reports samples available has changed, enable or disable next/prev buttons + // when reports available has changed, enable or disable next/prev buttons @Override - public void contentsChanged(SampleSource source) { + public void contentsChanged(ReportSource source) { if(source==currentSource) { togglePrevNextButtons(); } diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/ReportSource.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/ReportSource.java new file mode 100644 index 0000000..c563e94 --- /dev/null +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/ReportSource.java @@ -0,0 +1,11 @@ +package com.dell.gumshoe.inspector; + +import com.dell.gumshoe.inspector.tools.ReportSelectionListener; + +public interface ReportSource { + public void addListener(ReportSelectionListener listener); + public boolean hasNext(); + public boolean hasPrevious(); + public void nextReport(); + public void previousReport(); +} diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/SampleSource.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/SampleSource.java deleted file mode 100644 index 75b4bc6..0000000 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/SampleSource.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.dell.gumshoe.inspector; - -import com.dell.gumshoe.inspector.tools.SampleSelectionListener; - -public interface SampleSource { - public void addListener(SampleSelectionListener listener); - public boolean hasNext(); - public boolean hasPrevious(); - public void nextSample(); - public void previousSample(); -} diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/Tool.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/Tool.java index 8813f59..835e30d 100644 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/Tool.java +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/Tool.java @@ -2,7 +2,7 @@ import com.dell.gumshoe.inspector.tools.DetailPanel; import com.dell.gumshoe.inspector.tools.HasCloseButton; -import com.dell.gumshoe.inspector.tools.SampleFileChooser; +import com.dell.gumshoe.inspector.tools.ReportFileChooser; import javax.swing.AbstractButton; import javax.swing.ImageIcon; @@ -18,7 +18,7 @@ import java.net.URL; public enum Tool implements ActionListener { - CONFIGURE_PROBE("Select samples from this VM", "probe.png", "Manage Probes") { + CONFIGURE_PROBE("Select reports from this VM", "probe.png", "Manage Probes") { public void setComponents(GUIComponents components) { super.setComponents(components); if(getPopup()==null) { @@ -36,15 +36,15 @@ public void actionPerformed(ActionEvent e) { } }, - LOAD_PREVIOUS_SAMPLE("Previous sample", "prev.png") { + LOAD_PREVIOUS_REPORT("Previous report", "prev.png") { public void actionPerformed(ActionEvent e) { - targets.prevSample(); + targets.prevReport(); } }, - LOAD_NEXT_SAMPLE("Next sample", "next.png") { + LOAD_NEXT_REPORT("Next report", "next.png") { public void actionPerformed(ActionEvent e) { - targets.nextSample(); + targets.nextReport(); } }, @@ -153,8 +153,8 @@ public JDialog getProbePopup() { return popup; } - public SampleFileChooser getFileChooser() { - final SampleFileChooser out = gui.getFileControl(); + public ReportFileChooser getFileChooser() { + final ReportFileChooser out = gui.getFileControl(); setPosition(out); return out; } @@ -212,7 +212,7 @@ public void actionPerformed(ActionEvent e) { return probePopup; } - public void setPosition(SampleFileChooser window) { + public void setPosition(ReportFileChooser window) { final int index = DIALOG_COUNT++; int x = 100+(index%4)*75; final int y = 100+ index*50; @@ -232,14 +232,14 @@ public void setPosition(Window window) { public void zoomMax() { gui.zoomMax(); } public void zoomIn() { gui.zoomIn(); } public void zoomOut() { gui.zoomOut(); } - public void prevSample() { gui.previousSample(); } - public void nextSample() { gui.nextSample(); } + public void prevReport() { gui.previousReport(); } + public void nextReport() { gui.nextReport(); } } public static interface GUIComponents { public JFrame getFrame(); public JComponent getProbeControl(); - public SampleFileChooser getFileControl(); + public ReportFileChooser getFileControl(); public JComponent getFilterControl(); public JComponent getStatisticControl(); public JComponent getGraphControl(); @@ -249,7 +249,7 @@ public static interface GUIComponents { public void zoomFit(); public void zoomIn(); public void zoomOut(); - public void previousSample(); - public void nextSample(); + public void previousReport(); + public void nextReport(); } } \ No newline at end of file diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/graph/StackGraphPanel.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/graph/StackGraphPanel.java index f34a51a..a57b335 100644 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/graph/StackGraphPanel.java +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/graph/StackGraphPanel.java @@ -215,7 +215,7 @@ public void paintComponent(Graphics g) { g.setColor(Color.WHITE); g.fillRect(10, 10, 350, 50); g.setColor(Color.BLACK); - g.drawString("No data! Load a sample from a probe or file.", 30, 40); + g.drawString("No data! Load a report from a probe or file.", 30, 40); } else if(image==null || image.getHeight()!=dim.height || image.getWidth()!=dim.width) { g.setColor(getBackground()); g.fillRect(0,0,dim.width,dim.height); diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/OptionEditor.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/OptionEditor.java index 01dce02..ec05c77 100644 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/OptionEditor.java +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/OptionEditor.java @@ -29,11 +29,6 @@ public class OptionEditor extends JPanel implements HasCloseButton { private final JCheckBox byValue = new JCheckBox("arrange by statistic value (left to right)"); private final JTextField statLimit = new JTextField(); private final JButton apply = new JButton("OK"); -// private final JComboBox statSelector = new JComboBox(DataTypeHelper.getTypes().toArray()); -// private final CardLayout statCard = new CardLayout(); -// private final JPanel statOptions = new JPanel(); -// private String lastLoadedType; -// private boolean updateWhenLoaded = true; public OptionEditor() { groupButtons(byCalled, byCaller); @@ -53,45 +48,14 @@ public OptionEditor() { ///// -// statSelector.addActionListener(new ActionListener() { -// @Override -// public void actionPerformed(ActionEvent e) { -// final String label = (String)statSelector.getSelectedItem(); -// statCard.show(statOptions, label); -// // if user manually selects current displayed type, -// // keep them in sync if new type is loaded -// // otherwise leave it on user's selected type -// // so viewing stats live won't change dropdown while user choosing a stat -// updateWhenLoaded = label.equals(lastLoadedType); -// } -// }); -// final JPanel statChooserPanel = stackWest(new JLabel("For sample type "), statSelector, new JLabel(":")); -// statOptions.setBorder(BorderFactory.createEmptyBorder(5, 10, 10, 10)); -// -// statOptions.setLayout(statCard); -// for(String typeName : DataTypeHelper.getTypes()) { -// statOptions.add(DataTypeHelper.forType(typeName).getOptionEditor(), typeName); -// } -// final JPanel bottomPanel = stackSouth(flow(apply), graphPanel); -// statPanel = new JPanel(); -// statPanel.setLayout(new BorderLayout()); -// statPanel.add(statChooserPanel, BorderLayout.NORTH); -// statPanel.add(statOptions, BorderLayout.CENTER); -// titled("Select statistic to display", statPanel); setLayout(new BorderLayout()); add(bottomPanel, BorderLayout.SOUTH); -// add(statPanel, BorderLayout.CENTER); } -// final JPanel statPanel; - -// public JPanel getStatPanel() { return statPanel; } - public void addActionListener(ActionListener listener) { apply.addActionListener(listener); -// listener.actionPerformed(new ActionEvent(this, 0, "")); } public DisplayOptions getOptions() { @@ -112,13 +76,6 @@ public DisplayOptions getOptions() { return new DisplayOptions(isInverted, order, width, minPct); } -// public void chooseStatType(String type) { -// lastLoadedType = type; -// if(updateWhenLoaded) { -// statSelector.setSelectedItem(type); -// } -// } - @Override public void addCloseListener(ActionListener listener) { apply.addActionListener(listener); diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ProbeSourcePanel.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ProbeSourcePanel.java index 4e946df..7091541 100644 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ProbeSourcePanel.java +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ProbeSourcePanel.java @@ -5,7 +5,7 @@ import static com.dell.gumshoe.util.Swing.rows; import com.dell.gumshoe.ProbeManager; -import com.dell.gumshoe.inspector.SampleSource; +import com.dell.gumshoe.inspector.ReportSource; import com.dell.gumshoe.inspector.helper.DataTypeHelper; import com.dell.gumshoe.stack.Stack; import com.dell.gumshoe.stats.StatisticAdder; @@ -33,19 +33,19 @@ import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; -public class ProbeSourcePanel extends JPanel implements Listener, SampleSource, HasCloseButton { +public class ProbeSourcePanel extends JPanel implements Listener, ReportSource, HasCloseButton { private static final SimpleDateFormat hms = new SimpleDateFormat("HH:mm:ss"); private List closeListeners = new CopyOnWriteArrayList<>(); - private final List listeners = new CopyOnWriteArrayList<>(); - private final JRadioButton ignoreIncoming = new JRadioButton("drop new samples"); - private final JRadioButton dropOldest = new JRadioButton("drop oldest sample", true); + private final List listeners = new CopyOnWriteArrayList<>(); + private final JRadioButton ignoreIncoming = new JRadioButton("drop new reports"); + private final JRadioButton dropOldest = new JRadioButton("drop oldest report", true); private final JCheckBox sendLive = new JCheckBox("Immediately view newest"); - private final JButton sendNow = new JButton("View sample"); + private final JButton sendNow = new JButton("View report"); private final JButton ok = new JButton("OK"); - private int sampleCount = 3; - private final DefaultListModel sampleModel = new DefaultListModel(); - private final JList sampleList = new JList(sampleModel); + private int reportCount = 3; + private final DefaultListModel reportModel = new DefaultListModel(); + private final JList reportList = new JList(reportModel); public ProbeSourcePanel(ProbeManager probe) { super(new BorderLayout()); @@ -53,21 +53,21 @@ public ProbeSourcePanel(ProbeManager probe) { sendNow.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - final Sample selected = (Sample)sampleList.getSelectedValue(); + final Report selected = (Report)reportList.getSelectedValue(); if(selected!=null) { relayStats(selected); } } }); - sampleList.setVisibleRowCount(sampleCount); - sampleList.setPrototypeCellValue(new Sample("socket-io", new Date(), Collections.emptyMap())); - sampleList.addMouseListener(new MouseAdapter() { + reportList.setVisibleRowCount(reportCount); + reportList.setPrototypeCellValue(new Report("socket-io", new Date(), Collections.emptyMap())); + reportList.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if( ! sendNow.isSelected() && e.getClickCount()==2) { - int index = sampleList.locationToIndex(e.getPoint()); - final Sample selected = (Sample)sampleModel.getElementAt(index); + int index = reportList.locationToIndex(e.getPoint()); + final Report selected = (Report)reportModel.getElementAt(index); if(selected!=null) { relayStats(selected); } @@ -77,7 +77,7 @@ public void mouseClicked(MouseEvent e) { // row: which types of data to receive final JPanel acceptPanel = new JPanel(); - acceptPanel.add(new JLabel("Accept samples from probes:")); + acceptPanel.add(new JLabel("Accept reports from probes:")); for(String type : DataTypeHelper.getTypes()) { acceptPanel.add(DataTypeHelper.forType(type).getSelectionComponent()); } @@ -85,10 +85,10 @@ public void mouseClicked(MouseEvent e) { // row: how to handle full buffer final JTextField retainCount = new JTextField(); retainCount.setColumns(3); - retainCount.setText(Integer.toString(sampleCount)); + retainCount.setText(Integer.toString(reportCount)); groupButtons(ignoreIncoming, dropOldest); final JLabel fullLabel = new JLabel("Retain full:"); - final JPanel handleIncoming = flow(new JLabel("Retain"), retainCount, new JLabel("samples, then: "), ignoreIncoming, dropOldest); + final JPanel handleIncoming = flow(new JLabel("Retain"), retainCount, new JLabel("reports, then: "), ignoreIncoming, dropOldest); sendLive.addActionListener(new ActionListener() { @Override @@ -104,7 +104,7 @@ public void actionPerformed(ActionEvent e) { setLayout(new BorderLayout()); add(rows(acceptPanel, handleIncoming), BorderLayout.NORTH); - add(new JScrollPane(sampleList, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER); + add(new JScrollPane(reportList, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER); add(flow(sendNow, sendNow, ok), BorderLayout.SOUTH); if(probe!=null) { @@ -114,12 +114,12 @@ public void actionPerformed(ActionEvent e) { } } - private boolean canAccept(String sampleType, Map stats) { + private boolean canAccept(String reportType, Map stats) { if(stats.isEmpty()) { return false; } - // see if the box is checked to accept this sample type + // see if the box is checked to accept this report type for(String helperType : DataTypeHelper.getTypes()) { - if(helperType.equals(sampleType)) { + if(helperType.equals(reportType)) { if(DataTypeHelper.forType(helperType).isSelected()) { break; } else { @@ -129,9 +129,9 @@ private boolean canAccept(String sampleType, Map stats) { } // see if buffer has room or we can remove one - if(sampleModel.size()>=sampleCount) { + if(reportModel.size()>=reportCount) { if(ignoreIncoming.isSelected() && ! sendLive.isSelected()) { return false; } - sampleModel.removeElementAt(0); + reportModel.removeElementAt(0); } return true; } @@ -142,37 +142,37 @@ private boolean canAccept(String sampleType, Map stats) { public synchronized void statsReported(String type, Map stats) { if(canAccept(type, stats)) { final Date date = new Date(); - final Sample sample = new Sample(type, date, stats); + final Report report = new Report(type, date, stats); if(sendLive.isSelected()) { - sampleModel.clear(); + reportModel.clear(); } - sampleModel.addElement(sample); + reportModel.addElement(report); if(sendLive.isSelected()) { - relayStats(sample); + relayStats(report); } notifyContentsChanged(); } } - private void relayStats(Sample sample) { - for(SampleSelectionListener listener : listeners) { - listener.sampleWasSelected(this, sample.time, sample.type, sample.data); + private void relayStats(Report report) { + for(ReportSelectionListener listener : listeners) { + listener.reportWasSelected(this, report.time, report.type, report.data); } notifyCloseListeners(); } - public void addListener(SampleSelectionListener listener) { + public void addListener(ReportSelectionListener listener) { listeners.add(listener); } - private static class Sample { + private static class Report { String label; String time; String type; Map data; - public Sample(String type, Date sampleTime, Map data) { - this.time = hms.format(sampleTime); + public Report(String type, Date reportTime, Map data) { + this.time = hms.format(reportTime); this.label = time + " " + type + ": " + DataTypeHelper.forType(type).getSummary(data); this.type = type; this.data = data; @@ -184,39 +184,39 @@ public String toString() { } } - public void nextSample() { - final int size = sampleModel.getSize(); + public void nextReport() { + final int size = reportModel.getSize(); if(size==0) { return; } - final int currentIndex = sampleList.getSelectedIndex(); + final int currentIndex = reportList.getSelectedIndex(); if(currentIndex>=0) { - sampleList.setSelectedIndex(currentIndex+1); - relayStats((Sample) sampleList.getSelectedValue()); + reportList.setSelectedIndex(currentIndex+1); + relayStats((Report) reportList.getSelectedValue()); } else { - sampleList.setSelectedIndex(0); - relayStats((Sample) sampleList.getSelectedValue()); + reportList.setSelectedIndex(0); + relayStats((Report) reportList.getSelectedValue()); } } - public void previousSample() { - final int size = sampleModel.getSize(); + public void previousReport() { + final int size = reportModel.getSize(); if(size==0) { return; } - final int currentIndex = sampleList.getSelectedIndex(); + final int currentIndex = reportList.getSelectedIndex(); if(currentIndex>=0) { - sampleList.setSelectedIndex(currentIndex-1); - relayStats((Sample) sampleList.getSelectedValue()); + reportList.setSelectedIndex(currentIndex-1); + relayStats((Report) reportList.getSelectedValue()); } else { - sampleList.setSelectedIndex(size-1); - relayStats((Sample) sampleList.getSelectedValue()); + reportList.setSelectedIndex(size-1); + relayStats((Report) reportList.getSelectedValue()); } } @Override public boolean hasNext() { if(sendLive.isSelected()) { return false; } - final int size = sampleModel.getSize(); - final int selectedIndex = sampleList.getSelectedIndex(); + final int size = reportModel.getSize(); + final int selectedIndex = reportList.getSelectedIndex(); if(selectedIndex==-1) { return size>0; } return size > selectedIndex+1; } @@ -224,14 +224,14 @@ public boolean hasNext() { @Override public boolean hasPrevious() { if(sendLive.isSelected()) { return false; } - final int size = sampleModel.getSize(); - final int selectedIndex = sampleList.getSelectedIndex(); + final int size = reportModel.getSize(); + final int selectedIndex = reportList.getSelectedIndex(); if(selectedIndex==-1) { return size>0; } - return sampleList.getSelectedIndex()>0; + return reportList.getSelectedIndex()>0; } private void notifyContentsChanged() { - for(SampleSelectionListener listener : listeners) { + for(ReportSelectionListener listener : listeners) { listener.contentsChanged(this); } } diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/SampleFileChooser.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ReportFileChooser.java similarity index 77% rename from gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/SampleFileChooser.java rename to gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ReportFileChooser.java index d2b2ac9..e4338b5 100644 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/SampleFileChooser.java +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ReportFileChooser.java @@ -1,7 +1,7 @@ package com.dell.gumshoe.inspector.tools; import com.dell.gumshoe.inspector.FileDataParser; -import com.dell.gumshoe.inspector.SampleSource; +import com.dell.gumshoe.inspector.ReportSource; import com.dell.gumshoe.stack.Stack; import com.dell.gumshoe.stats.StatisticAdder; @@ -19,15 +19,15 @@ import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; -public class SampleFileChooser extends JFileChooser implements SampleSource { +public class ReportFileChooser extends JFileChooser implements ReportSource { private static final SimpleDateFormat hms = new SimpleDateFormat("HH:mm:ss"); - private final List listeners = new CopyOnWriteArrayList<>(); + private final List listeners = new CopyOnWriteArrayList<>(); private JDialog dialog; private FileDataParser parser; private int locationX, locationY; - public SampleFileChooser() { + public ReportFileChooser() { setApproveButtonText("Parse"); } @@ -76,7 +76,7 @@ private void openParser(File file) { } try { - readSample(true); + readReport(true); } catch(Exception ex) { ex.printStackTrace(); notifyError("Error parsing contents: " + ex.getMessage()); @@ -97,17 +97,17 @@ private boolean validFile(File file) { return true; } - private void readSample(boolean forward) { + private void readReport(boolean forward) { new FileOpener(forward).execute(); } - public void addListener(SampleSelectionListener listener) { + public void addListener(ReportSelectionListener listener) { listeners.add(listener); } private void relayStats(String file, String time, String type, Map data) { - for(SampleSelectionListener listener : listeners) { - listener.sampleWasSelected(file, time, type, data); + for(ReportSelectionListener listener : listeners) { + listener.reportWasSelected(file, time, type, data); } } @@ -118,16 +118,16 @@ public FileOpener(boolean forward) { } @Override public Map doInBackground() throws Exception { - return forward ? parser.getNextSample() : parser.getPreviousSample(); + return forward ? parser.getNextReport() : parser.getPreviousReport(); } @Override public void done() { try { - final Map sample = get(); - if(sample!=null) { - final Date time = parser.getSampleTime(); - final String sampleTime = hms.format(time); - relayStats(parser.getFilename(), parser.getSampleType(), sampleTime, sample); + final Map report = get(); + if(report!=null) { + final Date time = parser.getReportTime(); + final String reportTime = hms.format(time); + relayStats(parser.getFilename(), parser.getReportType(), reportTime, report); } } catch(Exception ex) { notifyError("Parse error reading file"); @@ -137,12 +137,12 @@ public void done() { ///// - public void nextSample() { - readSample(true); + public void nextReport() { + readReport(true); } - public void previousSample() { - readSample(false); + public void previousReport() { + readReport(false); } @Override @@ -156,7 +156,7 @@ public boolean hasPrevious() { } private void notifyContentsChanged() { - for(SampleSelectionListener listener : listeners) { + for(ReportSelectionListener listener : listeners) { listener.contentsChanged(this); } } diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ReportSelectionListener.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ReportSelectionListener.java new file mode 100644 index 0000000..abc9483 --- /dev/null +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/ReportSelectionListener.java @@ -0,0 +1,12 @@ +package com.dell.gumshoe.inspector.tools; + +import com.dell.gumshoe.inspector.ReportSource; +import com.dell.gumshoe.stack.Stack; +import com.dell.gumshoe.stats.StatisticAdder; + +import java.util.Map; + +public interface ReportSelectionListener { + public void reportWasSelected(Object source, String time, String type, Map data); + public void contentsChanged(ReportSource source); +} \ No newline at end of file diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/SampleSelectionListener.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/SampleSelectionListener.java deleted file mode 100644 index 4e0df77..0000000 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/SampleSelectionListener.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.dell.gumshoe.inspector.tools; - -import com.dell.gumshoe.inspector.SampleSource; -import com.dell.gumshoe.stack.Stack; -import com.dell.gumshoe.stats.StatisticAdder; - -import java.util.Map; - -public interface SampleSelectionListener { - public void sampleWasSelected(Object source, String time, String type, Map data); - public void contentsChanged(SampleSource source); -} \ No newline at end of file diff --git a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/StatisticChooser.java b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/StatisticChooser.java index 2d934ce..d3bcb9c 100644 --- a/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/StatisticChooser.java +++ b/gumshoe-tools/src/main/java/com/dell/gumshoe/inspector/tools/StatisticChooser.java @@ -4,7 +4,7 @@ import static com.dell.gumshoe.util.Swing.stackIn; import static com.dell.gumshoe.util.Swing.stackWest; -import com.dell.gumshoe.inspector.SampleSource; +import com.dell.gumshoe.inspector.ReportSource; import com.dell.gumshoe.inspector.graph.StackGraphPanel; import com.dell.gumshoe.inspector.helper.DataTypeHelper; import com.dell.gumshoe.stack.Stack; @@ -22,7 +22,7 @@ import java.awt.event.ActionListener; import java.util.Map; -public class StatisticChooser extends JPanel implements SampleSelectionListener, HasCloseButton { +public class StatisticChooser extends JPanel implements ReportSelectionListener, HasCloseButton { private final JComboBox statSelector = new JComboBox(DataTypeHelper.getTypes().toArray()); private final CardLayout statCard = new CardLayout(); private final JPanel statOptions = new JPanel(); @@ -47,7 +47,7 @@ public void actionPerformed(ActionEvent e) { updateWhenLoaded = label.equals(lastLoadedType); } }); - final JPanel statChooserPanel = stackWest(new JLabel("Select statistic for sample type "), statSelector, new JLabel(":")); + final JPanel statChooserPanel = stackWest(new JLabel("Select statistic for report type "), statSelector, new JLabel(":")); statOptions.setBorder(BorderFactory.createEmptyBorder(5, 10, 10, 10)); statOptions.setLayout(statCard); @@ -59,7 +59,7 @@ public void actionPerformed(ActionEvent e) { } @Override - public void sampleWasSelected(Object source, String time, String type, Map data) { + public void reportWasSelected(Object source, String time, String type, Map data) { lastLoadedType = type; if( ! isShowing()) { updateWhenLoaded = true; } if(updateWhenLoaded) { @@ -74,7 +74,7 @@ public void addCloseListener(ActionListener listener) { } @Override - public void contentsChanged(SampleSource source) { + public void contentsChanged(ReportSource source) { // no-op } } diff --git a/gumshoe-tools/src/test/java/com/dell/gumshoe/tools/TestFileReader.java b/gumshoe-tools/src/test/java/com/dell/gumshoe/tools/TestFileReader.java index 3dd80fc..7171826 100644 --- a/gumshoe-tools/src/test/java/com/dell/gumshoe/tools/TestFileReader.java +++ b/gumshoe-tools/src/test/java/com/dell/gumshoe/tools/TestFileReader.java @@ -27,46 +27,46 @@ public void tearDown() throws IOException { } public void testNavigating() throws Exception { - Map entry = target.getNextSample(); + Map entry = target.getNextReport(); assertEquals(7, entry.size()); - Date time1 = target.getSampleTime(); + Date time1 = target.getReportTime(); - entry = target.getNextSample(); - Date time2 = target.getSampleTime(); + entry = target.getNextReport(); + Date time2 = target.getReportTime(); assertEquals(2, entry.size()); assertTrue(time1.before(time2)); - entry = target.getNextSample(); - Date time3 = target.getSampleTime(); + entry = target.getNextReport(); + Date time3 = target.getReportTime(); assertEquals(2, entry.size()); assertTrue(time2.before(time3)); - entry = target.getPreviousSample(); - Date time4 = target.getSampleTime(); + entry = target.getPreviousReport(); + Date time4 = target.getReportTime(); assertEquals(2, entry.size()); assertEquals(time2, time4); - entry = target.getPreviousSample(); + entry = target.getPreviousReport(); assertNotNull(entry); - assertNotNull(target.getSampleTime()); - entry = target.getPreviousSample(); + assertNotNull(target.getReportTime()); + entry = target.getPreviousReport(); assertNull(entry); - assertNull(target.getSampleTime()); + assertNull(target.getReportTime()); } public void testDump() throws Exception { target.parseFile(); - List times = new ArrayList<>(target.getSampleTimes()); + List times = new ArrayList<>(target.getReportTimes()); assertEquals(3, times.size()); Date middle = times.get(1); - Map entry = target.getSample(middle); - Date time = target.getSampleTime(); + Map entry = target.getReport(middle); + Date time = target.getReportTime(); assertEquals(2, entry.size()); assertEquals(time, middle); - entry = target.getSample(new Date()); + entry = target.getReport(new Date()); assertNull(entry); - assertNull(target.getSampleTime()); + assertNull(target.getReportTime()); } } diff --git a/gumshoe-tools/unused/FileSourcePanel.java b/gumshoe-tools/unused/FileSourcePanel.java deleted file mode 100644 index a1bdea3..0000000 --- a/gumshoe-tools/unused/FileSourcePanel.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.dell.gumshoe.inspector; - -import static com.dell.gumshoe.util.Swing.flow; - -import com.dell.gumshoe.inspector.tools.SampleSelectionListener; -import com.dell.gumshoe.stack.Stack; -import com.dell.gumshoe.stats.StatisticAdder; - -import javax.swing.JButton; -import javax.swing.JFileChooser; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.SwingWorker; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; - -public class FileSourcePanel extends JPanel { - private static final SimpleDateFormat hms = new SimpleDateFormat("HH:mm:ss"); - - private final List listeners = new CopyOnWriteArrayList<>(); - - private FileDataParser file; - private StatisticsSourcePanel parent; - - private final JTextField fileNameField = new JTextField(); - private final JFileChooser fileChooser = new JFileChooser(); - private final JButton openButton = new JButton("Parse"); - - public FileSourcePanel(final StatisticsSourcePanel parent) { - this(); - setParent(parent); - } - - public FileSourcePanel() { - fileChooser.setApproveButtonText("Parse"); - final JButton chooseButton = new JButton("File:"); - chooseButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - final int result = fileChooser.showOpenDialog(FileSourcePanel.this); - if(result==JFileChooser.APPROVE_OPTION) { - fileNameField.setText(fileChooser.getSelectedFile().getAbsolutePath()); - openFile(); - } - } - }); - openButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - openFile(); - } - }); - fileNameField.setColumns(30); - - final JPanel fileNamePanel = flow(chooseButton, fileNameField, openButton); - -// final JButton back = new JButton("<< Previous"); -// back.addActionListener(new ActionListener() { -// @Override -// public void actionPerformed(ActionEvent e) { -// readSample(false); -// } -// }); -// final JButton forward = new JButton("Next >>"); -// forward.addActionListener(new ActionListener() { -// @Override -// public void actionPerformed(ActionEvent e) { -// readSample(true); -// } -// }); - -// final JPanel actionPanel = flow(back, forward); - setLayout(new BorderLayout()); -// add(fileNamePanel, BorderLayout.NORTH); -// add(actionPanel, BorderLayout.CENTER); - } - - public void setParent(StatisticsSourcePanel parent) { - this.parent = parent; - } - - - private void openFile() { - if(file!=null) { - try { file.close(); } - catch(Exception ex) { - ex.printStackTrace(); - } - file = null; - } - try { - final String fileName = fileNameField.getText(); - if("".equals(fileName.trim())) { - parent.setStatus("No file selected"); - } else if( ! new File(fileName).canRead()) { - parent.setStatus("Unable to read file"); - } else { - file = new FileDataParser(fileName); - openButton.setEnabled(false); - parent.setStatus("Reading file: " + fileName); - readSample(true); - } - } catch(Exception ex) { - ex.printStackTrace(); - } - } - - private class FileOpener extends SwingWorker,Object> { - private final boolean forward; - public FileOpener(boolean forward) { - this.forward = forward; - } - @Override - public Map doInBackground() throws Exception { - return forward ? file.getNextSample() : file.getPreviousSample(); - } - @Override - public void done() { - try { - final Map sample = get(); - if(sample==null) { - parent.setStatus("No more samples found in file"); - parent.setSample(null, null); - } else { - final Date time = file.getSampleTime(); - final String sampleTime = hms.format(time); - parent.setStatus("File sample time: " + sampleTime); - parent.setSample(sampleTime, sample); - } - } catch(Exception ex) { - parent.setStatus("Parse error reading file"); - parent.setSample(null, null); - } finally { - openButton.setEnabled(true); - } - } - } - - private void readSample(boolean forward) { - new FileOpener(forward).execute(); - } - - public void addListener(SampleSelectionListener listener) { - listeners.add(listener); - } - -} diff --git a/gumshoe-tools/unused/StatisticsSourcePanel.java b/gumshoe-tools/unused/StatisticsSourcePanel.java deleted file mode 100644 index 2e43cf8..0000000 --- a/gumshoe-tools/unused/StatisticsSourcePanel.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.dell.gumshoe.inspector; -import static com.dell.gumshoe.util.Swing.flow; -import static com.dell.gumshoe.util.Swing.groupButtons; -import static com.dell.gumshoe.util.Swing.stackNorth; - -import com.dell.gumshoe.ProbeManager; -import com.dell.gumshoe.inspector.tools.ProbeSourcePanel; -import com.dell.gumshoe.stack.Stack; -import com.dell.gumshoe.stats.StatisticAdder; - -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JRadioButton; - -import java.awt.BorderLayout; -import java.awt.CardLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.text.SimpleDateFormat; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; - -public class StatisticsSourcePanel extends JPanel { - static final SimpleDateFormat hms = new SimpleDateFormat("HH:mm:ss"); - - private final FileSourcePanel fileSource; - private final ProbeSourcePanel probeSource; - private final JPanel cardPanel = new JPanel(); - private final CardLayout sourceCardLayout = new CardLayout(); - private final JLabel status = new JLabel("No data currently displayed"); - - public StatisticsSourcePanel(ProbeManager probe) { - this(new FileSourcePanel(), new ProbeSourcePanel(probe)); - } - - public StatisticsSourcePanel(FileSourcePanel fileSource, ProbeSourcePanel probeSource) { - this.fileSource = fileSource; - this.probeSource = probeSource; - fileSource.setParent(this); -// probeSource.setParent(this); - - final JRadioButton jvmButton = new JRadioButton("probe this JVM"); - jvmButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - sourceCardLayout.show(cardPanel, "jvm"); - } - }); - final JRadioButton fileButton = new JRadioButton("text file"); - fileButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - sourceCardLayout.show(cardPanel, "file"); - } - }); - - groupButtons(jvmButton, fileButton); - final JPanel sourcePanel = flow(new JLabel("Source:"), jvmButton, fileButton); - - cardPanel.setLayout(sourceCardLayout); -// cardPanel.add(fileSource, "file"); -// cardPanel.add(probeSource, "jvm"); - - setLayout(new BorderLayout()); - add(stackNorth(flow(status), sourcePanel, cardPanel), BorderLayout.NORTH); - - // if there is a main, that is the default source -// if(probe!=null) { - jvmButton.setSelected(true); - sourceCardLayout.show(cardPanel, "jvm"); -// } else { -// jvmButton.setEnabled(false); -// fileButton.setSelected(true); -// sourceCardLayout.show(cardPanel, "file"); -// } - } - - public void setStatus(String message) { - status.setText(message); - } - - public void setSample(String time, Map stats) { - if(stats!=null) { - final String type = stats.values().iterator().next().getType(); - notifyListeners(time, type, stats); - } else { - notifyListeners(null, null, null); - } - } - - ///// - - private List listeners = new CopyOnWriteArrayList<>(); - - public void addListener(Listener listener) { - listeners.add(listener); - } - - private void notifyListeners(String time, String type, Map stats) { - for(Listener listener : listeners) { - listener.statisticsLoaded(time, type, stats); - } - } - - public interface Listener { - public void statisticsLoaded(String time, String type, Map stats); - } -}