Author: ravn Date: Thu Oct 2 00:26:24 2008 New Revision: 1157 Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/JavassistHelper.java slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java
Log: now usable as a javaagent, tested with log4j Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java ============================================================================== --- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java (original) +++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java Thu Oct 2 00:26:24 2008 @@ -2,11 +2,11 @@ import static org.slf4j.helpers.MessageFormatter.format; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.lang.instrument.Instrumentation; -import java.util.Arrays; import java.util.Date; -import java.util.HashSet; -import java.util.Set; +import java.util.Properties; import org.slf4j.instrumentation.LogTransformer; @@ -20,25 +20,40 @@ LogTransformer.Builder builder = new LogTransformer.Builder(); builder = builder.addEntryExit(true); - + if (agentArgument != null) { - String[] args = agentArgument.split(","); - Set<String> argSet = new HashSet<String>(Arrays.asList(args)); + Properties args = parseArguments(agentArgument); - if (argSet.contains("verbose")) { + if (args.containsKey("verbose")) { builder = builder.verbose(true); } - - if (argSet.contains("time")) { + + if (args.containsKey("time")) { printStartStopTimes(); } - + + if (args.containsKey("ignore")) { + builder = builder.ignore(args.getProperty("ignore").split(",")); + } + // ... more agent option handling here } instrumentation.addTransformer(builder.build()); } + private static Properties parseArguments(String agentArgument) { + Properties p = new Properties(); + try { + byte[] bytes = agentArgument.replaceAll(";", "\n").getBytes(); + p.load(new ByteArrayInputStream(bytes)); + } catch (IOException e) { + throw new RuntimeException( + "Could not load arguments as properties", e); + } + return p; + } + /** * Print the start message with the time NOW, and register a shutdown hook * which will print the stop message with the time then and the number of Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/JavassistHelper.java ============================================================================== --- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/JavassistHelper.java (original) +++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/JavassistHelper.java Thu Oct 2 00:26:24 2008 @@ -68,7 +68,7 @@ sb.append("\"+ $" + (i + 1)); } } - sb.append("+\")\""); + sb.append("+\")"); String signature = sb.toString(); return signature; Modified: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java ============================================================================== --- slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java (original) +++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java Thu Oct 2 00:26:24 2008 @@ -16,15 +16,41 @@ import javassist.CtField; import javassist.NotFoundException; +import org.slf4j.helpers.MessageFormatter; + +/** + * LogTransformer does the work of analyzing each class, and if appropriate add + * log statements to each method to allow logging entry/exit. + * + */ public class LogTransformer implements ClassFileTransformer { + // http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html public static class Builder { + + /** + * Build and return the LogTransformer corresponding to the options set + * in this Builder. + * + * @return + */ public LogTransformer build() { + if (verbose) { + System.err.println("Creating LogTransformer"); + } return new LogTransformer(this); } boolean addEntryExit; + /** + * Should each method log entry (with parameters) and exit (with + * parameters and returnvalue)? + * + * @param b + * value of flag + * @return + */ public Builder addEntryExit(boolean b) { addEntryExit = b; return this; @@ -32,38 +58,59 @@ boolean addVariableAssignment; - public Builder addVariableAssignment(boolean b) { + private Builder addVariableAssignment(boolean b) { System.err.println("cannot currently log variable assignments."); addVariableAssignment = b; return this; } + boolean verbose; + /** + * Should LogTransformer be verbose in what it does? This currently list + * the names of the classes being processed. + * + * @param b + * @return + */ public Builder verbose(boolean b) { verbose = b; return this; } + + String[] ignore = { "sun/", "java/", "javax/", "org/slf4j/", + "ch/qos/logback/" , "org/apache/log4j/"}; + public Builder ignore(String[] strings) { + this.ignore = strings; + return this; + } } - private LogTransformer(Builder builder) { this.addEntryExit = builder.addEntryExit; this.addVariableAssignment = builder.addVariableAssignment; this.verbose = builder.verbose; + this.ignore = builder.ignore; } private static final String _LOG = "_log"; - String[] ignore = { "sun/", "java/", "javax/", "org/slf4j/", - "ch/qos/logback/" }; private boolean addEntryExit; private boolean addVariableAssignment; private boolean verbose; + private String[] ignore; public byte[] transform(ClassLoader loader, String className, Class<?> clazz, ProtectionDomain domain, byte[] bytes) { + - return transform0(className, clazz, bytes); + try { + return transform0(className, clazz, bytes); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return bytes; + } } /** @@ -152,12 +199,14 @@ if (addEntryExit) { String messagePattern = "if ({}.isDebugEnabled()) {}.info(\">> {}\");"; Object[] arg1 = new Object[] { _LOG, _LOG, signature }; - String before = format(messagePattern, arg1); + String before = MessageFormatter.arrayFormat(messagePattern, arg1); + //System.out.println(before); method.insertBefore(before); String messagePattern2 = "if ({}.isDebugEnabled()) {}.info(\"<< {}{}\");"; Object[] arg2 = new Object[] { _LOG, _LOG, signature, returnValue }; - String after = format(messagePattern2, arg2); + String after = MessageFormatter.arrayFormat(messagePattern2, arg2); + //System.out.println(after); method.insertAfter(after); } } _______________________________________________ dev mailing list dev@slf4j.org http://www.slf4j.org/mailman/listinfo/dev