Skip to content

Commit

Permalink
#27. Cluing vertical instrumentation parts together
Browse files Browse the repository at this point in the history
  • Loading branch information
kocherovms committed Apr 2, 2016
1 parent 7be9d72 commit caf0183
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 17 deletions.
76 changes: 74 additions & 2 deletions src/it/java/com/develorium/metracer/MainIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ public void testInstrumentAndQuitWithoutRemovalWithConsequentRemoval() throws Th

public static class InstrumentationOutputScenario extends Scenario {
private String pid = null;
Pattern pattern = Pattern.compile(
private Pattern pattern = Pattern.compile(
"\\+\\+\\+ \\[0\\] com.develorium.metracertest.Main.testBundle.*" +
"\\+\\+\\+ \\[1\\] com.develorium.metracertest.Main.testIntRetVal.*" +
"\\-\\-\\- \\[1\\] com.develorium.metracertest.Main.testIntRetVal.*" +
Expand Down Expand Up @@ -326,7 +326,7 @@ public void testInstrumentationOutput() {

public static class InstrumentationOutputWithStackTracesScenario extends Scenario {
private String pid = null;
Pattern pattern = Pattern.compile(
private Pattern pattern = Pattern.compile(
"\\[0\\] com.develorium.metracertest.Main.testStackTrace4.*" +
"\\s+at\\s+com.develorium.metracertest.Main.testStackTrace4.*" +
"\\s+at\\s+com.develorium.metracertest.Main.testStackTrace3.*" +
Expand Down Expand Up @@ -360,6 +360,78 @@ public void testInstrumentationOutputWithStackTraces() {
runMetracerScenario(scenario);
}

public static class InstrumentationWithStackTracesSavingScenario extends Scenario {
private String pid = null;
private String fileName = null;
private Pattern pattern = Pattern.compile(
"\\[0\\] com.develorium.metracertest.Main.testStackTrace4.*" +
"\\s+at\\s+com.develorium.metracertest.Main.testStackTrace4.*" +
"\\s+at\\s+com.develorium.metracertest.Main.testStackTrace3.*" +
"\\s+at\\s+com.develorium.metracertest.Main.testStackTrace2.*" +
"\\s+at\\s+com.develorium.metracertest.Main.testStackTrace1.*" +
"\\s+at\\s+com.develorium.metracertest.Main.testStackTrace0.*", Pattern.DOTALL);

public InstrumentationWithStackTracesSavingScenario(String thePid, String theFileName) {
pid = thePid;
fileName = theFileName;
}

@Override
public String[] getLaunchArguments() {
return new String[] { "-v", "-S", fileName, pid, "com.develorium.metracertest.Main", "testStackTrace4" };
}

@Override
public int process() {
printNewStdout();

if(pattern.matcher(stdout.toString()).find())
return 'q';

return 0;
}
}

public static class InstrumentWithPatternsFromFileScenario extends Scenario {
private String pid = null;
private String fileName = null;
private Pattern pattern = Pattern.compile(
"\\[0\\] com.develorium.metracertest.Main.testStackTrace0.*" +
"\\[1\\] com.develorium.metracertest.Main.testStackTrace1.*" +
"\\[2\\] com.develorium.metracertest.Main.testStackTrace2.*" +
"\\[3\\] com.develorium.metracertest.Main.testStackTrace3.*" +
"\\[4\\] com.develorium.metracertest.Main.testStackTrace4.*", Pattern.DOTALL);

public InstrumentWithPatternsFromFileScenario(String thePid, String theFileName) {
pid = thePid;
fileName = theFileName;
}

@Override
public String[] getLaunchArguments() {
return new String[] { "-v", "-f", fileName, pid };
}

@Override
public int process() {
printNewStdout();

if(pattern.matcher(stdout.toString()).find())
return 'q';

return 0;
}
}

@Test(timeout = 5000)
public void testVerticalInstrumentation() {
String fileName = String.format("%s/target/stacktrace.txt", System.getProperty("basedir"));
Scenario saveStackTracesScenario = new InstrumentationWithStackTracesSavingScenario(pid, fileName);
runMetracerScenario(saveStackTracesScenario);
Scenario instrumentWithPatternsFromFileScenario = new InstrumentWithPatternsFromFileScenario(pid, fileName);
runMetracerScenario(instrumentWithPatternsFromFileScenario);
}

private static void runMetracerScenario(Scenario theScenario) {
String[] launchArguments = theScenario.getLaunchArguments();
StringBuilder launchArgumentsStringified = new StringBuilder();
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/com/develorium/metracer/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class Main {
MBeanServerConnection connection = null;
ObjectName agentMxBeanName = null;
AgentMXBean agent = null;
PatternsFile outputPatternsFile = null;

public static void main(String[] theArguments) {
try {
Expand Down Expand Up @@ -92,6 +93,15 @@ private void executeInstrument() {
say("Not setting any patterns, using ones from a previous session");
}
else {
if(config.isWithStackTrace && config.stackTraceFileName != null) {
try {
FileOutputStream outputStream = new FileOutputStream(config.stackTraceFileName);
outputPatternsFile = new PatternsFile(outputStream);
} catch(FileNotFoundException e) {
throw new RuntimeException(String.format("Failed to open \"%s\" for writing: %s", config.stackTraceFileName, e.getMessage()), e);
}
}

StackTraceMode stackTraceMode = config.isWithStackTrace
? (config.stackTraceFileName != null
? StackTraceMode.PRINT_AND_REPORT
Expand Down Expand Up @@ -187,8 +197,12 @@ public void handleNotification(Notification theNotification, Object theHandback)

if(notificationType.equals(JmxNotificationTypes.EntryExitNotificationType))
stdout.println(theNotification.getMessage());
else if(notificationType.equals(JmxNotificationTypes.StackTraceNotificationType))
;
else if(notificationType.equals(JmxNotificationTypes.StackTraceNotificationType) && outputPatternsFile != null)
try {
outputPatternsFile.consumePatterns(theNotification.getMessage());
} catch(IOException e) {
stderr.format("Failed to write new patterns: %s\n", e.getMessage());
}
}
},
null, null);
Expand Down
8 changes: 2 additions & 6 deletions src/main/java/com/develorium/metracer/PatternsFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public String getMethodMatchingPattern() {
return methodMatchingPattern;
}

public void consumePatterns(String thePatterns, String theContext) throws IOException {
public void consumePatterns(String thePatterns) throws IOException {
if(writer == null)
throw new RuntimeException("PatternsFile is not initialized for writing");

Expand All @@ -55,11 +55,7 @@ public void consumePatterns(String thePatterns, String theContext) throws IOExce
return;

consumedPatterns.add(thePatterns);
writer.write(String.format("# stack trace no. %d\n", ++patternsSerial));

if(theContext != null && !theContext.isEmpty())
writer.write(String.format("# %s\n", theContext));

writer.write(String.format("# patterns set no. %d\n", ++patternsSerial));
writer.write(thePatterns);
writer.write("\n\n");
writer.flush();
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/develorium/metracer/dynamic/Agent.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ public void printMessage(Class<?> theClass, String theMethodName, String theMess

if(theStackTraceElements != null && p.getStackTraceMode() == StackTraceMode.PRINT_AND_REPORT) {
StringBuilder stackTraceMessage = new StringBuilder();
stackTraceMessage.append(String.format("# %s\n", theMessage));

for(StackTraceElement stackTraceElement : theStackTraceElements)
stackTraceMessage.append(String.format("%s::%s", stackTraceElement.getClassName(), stackTraceElement.getMethodName()));
stackTraceMessage.append(String.format("%s::%s\n", stackTraceElement.getClassName(), stackTraceElement.getMethodName()));

notification = new Notification(JmxNotificationTypes.StackTraceNotificationType, this, messageSerial.incrementAndGet(), stackTraceMessage.toString());
sendNotification(notification);
Expand Down
12 changes: 6 additions & 6 deletions src/test/java/com/develorium/metracer/PatternsFileTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ public void testLoadingOfBadPatterns() throws IOException {
public void testPatternsConsumption() throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PatternsFile file = new PatternsFile(outputStream);
file.consumePatterns("com.develorium.metracer.Test::method", "Some context");
file.consumePatterns("com.develorium.metracer.Test::method");
Assert.assertTrue(outputStream.toString().contains("com.develorium.metracer.Test::method"));
file.consumePatterns("com.acme.www.Servlet::doPerform\ncom.acme.www.Servlet::doBuild", "Another context");
file.consumePatterns("com.acme.www.Servlet::doPerform\ncom.acme.www.Servlet::doBuild");
Assert.assertTrue(outputStream.toString().contains("com.acme.www.Servlet::doPerform"));
Assert.assertTrue(outputStream.toString().contains("com.acme.www.Servlet::doBuild"));
}
Expand All @@ -128,10 +128,10 @@ public void testPatternsConsumption() throws IOException {
public void testDuplicationProtectionDuringPatternsConsumption() throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PatternsFile file = new PatternsFile(outputStream);
file.consumePatterns("x.y.z.MyClass::method1", "Some context");
file.consumePatterns("x.y.z.MyClass::method1");
int size = outputStream.size();

file.consumePatterns("x.y.z.MyClass::method1", "Some context");
file.consumePatterns("x.y.z.MyClass::method1");
Assert.assertTrue(size == outputStream.size());
}

Expand All @@ -149,8 +149,8 @@ public void testPatternsRecovery() throws IOException {
"a.b.c.HisClass::buildy\n" +
"a.b.c.HisClass::buildz\n";

file.consumePatterns(stackTrace1, "Some context");
file.consumePatterns(stackTrace2, "Some context");
file.consumePatterns("# Comment 1\n" + stackTrace1);
file.consumePatterns("# Comment 2\n" + stackTrace2);

String content = outputStream.toString();
ByteArrayInputStream inputStream = new ByteArrayInputStream(content.getBytes());
Expand Down

0 comments on commit caf0183

Please sign in to comment.