[slf4j-dev] svn commit: r1157 - in slf4j/trunk/slf4j-ext/src/main/java/org/slf4j: agent instrumentation

ravn at slf4j.org ravn at slf4j.org
Thu Oct 2 00:26:25 CEST 2008


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);
 		}
 	}



More information about the slf4j-dev mailing list