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

Ralph Goers ralph.goers at dslextreme.com
Wed Oct 1 22:53:36 CEST 2008


Can you describe how this is intended to work? Does this inject logging 
at runtime or build time?

ravn at slf4j.org wrote:
> Author: ravn
> Date: Wed Oct  1 21:57:55 2008
> New Revision: 1155
>
> Added:
>    slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java   (contents, props changed)
>       - copied, changed from r1154, /slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentMain.java
>    slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java   (contents, props changed)
>       - copied, changed from r1154, /slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/AddEntryExitLoggingTransformer.java
> Removed:
>    slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentMain.java
>    slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/AddEntryExitLoggingTransformer.java
>
> Log:
> beginning to generalize premain() and log transformer (which now has a builder)
>
> Copied: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java (from r1154, /slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentMain.java)
> ==============================================================================
> --- /slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentMain.java	(original)
> +++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/agent/AgentPremain.java	Wed Oct  1 21:57:55 2008
> @@ -1,37 +1,62 @@
>  package org.slf4j.agent;
>  
> +import static org.slf4j.helpers.MessageFormatter.format;
> +
>  import java.lang.instrument.Instrumentation;
>  import java.util.Arrays;
>  import java.util.Date;
>  import java.util.HashSet;
>  import java.util.Set;
>  
> -import org.slf4j.instrumentation.AddEntryExitLoggingTransformer;
> +import org.slf4j.instrumentation.LogTransformer;
> +
> +public class AgentPremain {
>  
> -public class AgentMain {
> +	private static final String START_MSG = "Start at {}";
> +	private static final String STOP_MSG = "Stop at {}, execution time = {} ms";
>  
>  	public static void premain(String agentArgument,
>  			Instrumentation instrumentation) {
>  
> +		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));
>  
> +			if (argSet.contains("verbose")) {
> +				builder = builder.verbose(true);
> +			}
> +			
>  			if (argSet.contains("time")) {
> -				final long start = System.currentTimeMillis();
> -				System.out.println("Start at " + new Date());
> -				Runtime.getRuntime().addShutdownHook(new Thread() {
> -					public void run() {
> -						System.out.println("Stop at " + new Date()
> -								+ ", execution time = "
> -								+ (System.currentTimeMillis() - start) + " ms");
> -					}
> -				});
> +				printStartStopTimes();
>  			}
> +			
>  			// ... more agent option handling here
>  		}
>  
> -		instrumentation.addTransformer(new AddEntryExitLoggingTransformer());
> +		instrumentation.addTransformer(builder.build());
> +	}
> +
> +	/**
> +	 * 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
> +	 * milliseconds passed since.
> +	 * 
> +	 */
> +	private static void printStartStopTimes() {
> +		final long start = System.currentTimeMillis();
> +		System.err.println(format(START_MSG, new Date()));
> +
> +		Thread hook = new Thread() {
> +			public void run() {
> +				long timePassed = System.currentTimeMillis() - start;
> +				String message = format(STOP_MSG, new Date(), timePassed);
> +				System.err.println(message);
> +			}
> +		};
> +		Runtime.getRuntime().addShutdownHook(hook);
>  	}
>  
>  }
> \ No newline at end of file
>
> Copied: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java (from r1154, /slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/AddEntryExitLoggingTransformer.java)
> ==============================================================================
> --- /slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/AddEntryExitLoggingTransformer.java	(original)
> +++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/instrumentation/LogTransformer.java	Wed Oct  1 21:57:55 2008
> @@ -16,21 +16,75 @@
>  import javassist.CtField;
>  import javassist.NotFoundException;
>  
> -public class AddEntryExitLoggingTransformer implements ClassFileTransformer {
> +public class LogTransformer implements ClassFileTransformer {
> +
> +	public static class Builder {
> +		public LogTransformer build() {
> +			return new LogTransformer(this);
> +		}
> +
> +		boolean addEntryExit;
> +
> +		public Builder addEntryExit(boolean b) {
> +			addEntryExit = b;
> +			return this;
> +		}
> +
> +		boolean addVariableAssignment;
> +
> +		public Builder addVariableAssignment(boolean b) {
> +			System.err.println("cannot currently log variable assignments.");
> +			addVariableAssignment = b;
> +			return this;
> +		}
> +		boolean verbose;
> +
> +		public Builder verbose(boolean b) {
> +			verbose = b;
> +			return this;
> +		}
> +	}
> +
> +
> +	private LogTransformer(Builder builder) {
> +		this.addEntryExit = builder.addEntryExit;
> +		this.addVariableAssignment = builder.addVariableAssignment;
> +		this.verbose = builder.verbose;
> +	}
>  
>  	private static final String _LOG = "_log";
> -	String[] ignore = new String[] { "sun/", "java/", "javax/", "org/slf4j/",
> +	String[] ignore = { "sun/", "java/", "javax/", "org/slf4j/",
>  			"ch/qos/logback/" };
>  
> +	private boolean addEntryExit;
> +	private boolean addVariableAssignment;
> +	private boolean verbose;
> +
>  	public byte[] transform(ClassLoader loader, String className,
>  			Class<?> clazz, ProtectionDomain domain, byte[] bytes) {
>  
> +		return transform0(className, clazz, bytes);
> +	}
> +
> +	/**
> +	 * transform0 sees if the className starts with any of the namespaces to
> +	 * ignore, if so it is returned unchanged. Otherwise it is processed by
> +	 * doClass(...)
> +	 * 
> +	 * @param className
> +	 * @param clazz
> +	 * @param bytes
> +	 * @return
> +	 */
> +	private byte[] transform0(String className, Class<?> clazz, byte[] bytes) {
>  		for (int i = 0; i < ignore.length; i++) {
>  			if (className.startsWith(ignore[i])) {
>  				return bytes;
>  			}
>  		}
> -		// System.out.println("Adding to " + className);
> +		if (verbose) {
> +			System.err.println("Loggifying " + className);
> +		}
>  		return doClass(className, clazz, bytes);
>  	}
>  
> @@ -95,14 +149,16 @@
>  		String signature = JavassistHelper.getSignature(method);
>  		String returnValue = JavassistHelper.returnValue(method);
>  
> -		String messagePattern = "if ({}.isDebugEnabled()) {}.info(\">> {}\");";
> -		Object[] arg1 = new Object[] { _LOG, _LOG, signature };
> -		String before = format(messagePattern, arg1);
> -		method.insertBefore(before);
> -
> -		String messagePattern2 = "if ({}.isDebugEnabled()) {}.info(\"<< {}{}\");";
> -		Object[] arg2 = new Object[] { _LOG, _LOG, signature, returnValue };
> -		String after = format(messagePattern2, arg2);
> -		method.insertAfter(after);
> +		if (addEntryExit) {
> +			String messagePattern = "if ({}.isDebugEnabled()) {}.info(\">> {}\");";
> +			Object[] arg1 = new Object[] { _LOG, _LOG, signature };
> +			String before = format(messagePattern, arg1);
> +			method.insertBefore(before);
> +
> +			String messagePattern2 = "if ({}.isDebugEnabled()) {}.info(\"<< {}{}\");";
> +			Object[] arg2 = new Object[] { _LOG, _LOG, signature, returnValue };
> +			String after = format(messagePattern2, arg2);
> +			method.insertAfter(after);
> +		}
>  	}
>  }
> \ No newline at end of file
> _______________________________________________
> dev mailing list
> dev at slf4j.org
> http://www.slf4j.org/mailman/listinfo/dev
>   



More information about the slf4j-dev mailing list