You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sirona.apache.org by rm...@apache.org on 2013/11/26 17:16:30 UTC
svn commit: r1545708 - in /incubator/sirona/trunk/agent/javaagent/src:
main/java/org/apache/sirona/javaagent/
main/java/org/apache/sirona/javaagent/listener/
main/java/org/apache/sirona/javaagent/spi/
test/java/org/apache/sirona/javaagent/ test/java/or...
Author: rmannibucau
Date: Tue Nov 26 16:16:29 2013
New Revision: 1545708
URL: http://svn.apache.org/r1545708
Log:
adding a test to show how to do a custom InvocationListener + adding ConfigurableListener helper
Added:
incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/ConfigurableListener.java
incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/HttpUrlConnectionAddHeaderTest.java
incubator/sirona/trunk/agent/javaagent/src/test/resources/
incubator/sirona/trunk/agent/javaagent/src/test/resources/META-INF/
incubator/sirona/trunk/agent/javaagent/src/test/resources/META-INF/services/
incubator/sirona/trunk/agent/javaagent/src/test/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener
Modified:
incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java
incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java
incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java
incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/CounterListener.java
incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/InvocationListener.java
incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java
incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/AgentPerfInterceptorAgentContractTest.java
incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/IncludeExcludeTest.java
Modified: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java?rev=1545708&r1=1545707&r2=1545708&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java Tue Nov 26 16:16:29 2013
@@ -134,18 +134,18 @@ public class AgentContext {
context.put(key, data);
}
- public void stop() {
- stopListeners(null);
+ public void stop(final Object result) {
+ stopListeners(result, null);
}
public void stopWithException(final Throwable error) {
- stopListeners(error);
+ stopListeners(null, error);
}
- private void stopListeners(final Throwable error) {
+ private void stopListeners(final Object result, final Throwable error) {
if (hasListeners) {
for (final InvocationListener listener : listeners) {
- listener.after(this, error);
+ listener.after(this, result, error);
}
}
}
Modified: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java?rev=1545708&r1=1545707&r2=1545708&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaAgent.java Tue Nov 26 16:16:29 2013
@@ -24,6 +24,7 @@ import org.objectweb.asm.ClassWriter;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
import java.security.ProtectionDomain;
public class SironaAgent {
@@ -36,6 +37,13 @@ public class SironaAgent {
Configuration.is("", true); // a touch to force eager init
instrumentation.addTransformer(new SironaTransformer(agentArgs), true);
+ try {
+ instrumentation.retransformClasses(SironaAgent.class.getClassLoader().loadClass("sun.net.www.protocol.http.HttpURLConnection"));
+ } catch (UnmodifiableClassException e) {
+ e.printStackTrace();
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
}
@@ -79,29 +87,30 @@ public class SironaAgent {
}
private byte[] doTransform(final String className, final byte[] classfileBuffer) {
- final ClassReader reader = new ClassReader(classfileBuffer);
- final ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
- final SironaClassVisitor advisor = new SironaClassVisitor(writer, className);
try {
+ final ClassReader reader = new ClassReader(classfileBuffer);
+ final ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
+ final SironaClassVisitor advisor = new SironaClassVisitor(writer, className);
reader.accept(advisor, ClassReader.SKIP_DEBUG);
+ return writer.toByteArray();
} catch (final RuntimeException re) {
- re.printStackTrace(); // log it otherwise hard to know if it fails
+ if (Boolean.getBoolean("sirona.agent.debug")) {
+ re.printStackTrace();
+ }
throw re;
}
- return writer.toByteArray();
}
private boolean shouldTransform(final String className, final ClassLoader loader) {
- return !(
- loader == null
- || className == null
- || loader.getClass().getName().equals(DELEGATING_CLASS_LOADER)
- || className.startsWith("org/apache/sirona")
- || className.startsWith("com/sun/proxy")
- )
+ return !(loader == null // bootstrap classloader
+ || className == null // framework with bug
+ || loader.getClass().getName().equals(DELEGATING_CLASS_LOADER)
+ || className.startsWith("sun/reflect")
+ || className.startsWith("com/sun/proxy")
+ || className.startsWith("org/apache/sirona"))
+
&& includeEvaluator.matches(className.replace("/", "."))
&& !excludeEvaluator.matches(className.replace("/", "."));
-
}
}
}
Modified: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java?rev=1545708&r1=1545707&r2=1545708&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/SironaClassVisitor.java Tue Nov 26 16:16:29 2013
@@ -143,6 +143,7 @@ public class SironaClassVisitor extends
private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
private static final Type[] STOP_WITH_THROWABLE_ARGS_TYPES = new Type[]{ THROWABLE_TYPE };
private static final Type OBJECT_TYPE = Type.getType(Object.class);
+ private static final Type[] STOP_WITH_OBJECT_ARGS_TYPES = new Type[]{ OBJECT_TYPE };
private static final Type[] START_ARGS_TYPES = new Type[]{ KEY_TYPE, OBJECT_TYPE };
// methods
@@ -185,7 +186,12 @@ public class SironaClassVisitor extends
// take metrics before returning
loadLocal(agentIdx);
- invokeVirtual(AGENT_CONTEXT, new Method(STOP_METHOD, NO_PARAM_RETURN_VOID));
+ if (result != -1) {
+ loadLocal(result);
+ } else {
+ visitInsn(ACONST_NULL); // result == null for static methods
+ }
+ invokeVirtual(AGENT_CONTEXT, new Method(STOP_METHOD, Type.VOID_TYPE, STOP_WITH_OBJECT_ARGS_TYPES));
// return result
returnResult(result);
Added: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/ConfigurableListener.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/ConfigurableListener.java?rev=1545708&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/ConfigurableListener.java (added)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/ConfigurableListener.java Tue Nov 26 16:16:29 2013
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sirona.javaagent.listener;
+
+import org.apache.sirona.configuration.predicate.PredicateEvaluator;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.javaagent.AgentContext;
+import org.apache.sirona.javaagent.spi.InvocationListener;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public abstract class ConfigurableListener implements InvocationListener {
+ private static final AtomicInteger ID_GENERATOR = new AtomicInteger(1); // 0 is reserved for CounterListener
+
+ private int id = ID_GENERATOR.incrementAndGet();
+
+ private PredicateEvaluator includes = new PredicateEvaluator("true:true", ",");
+ private PredicateEvaluator excludes = new PredicateEvaluator(null, null);
+
+ protected void before(final Counter.Key key, final Object reference) {
+ // no-op
+ }
+
+ protected void onSuccess(final Counter.Key key, final Object reference, final Object result) {
+ // no-op
+ }
+
+ protected void onError(final Counter.Key key, final Object reference, final Throwable error) {
+ // no-op
+ }
+
+ @Override
+ public void before(final AgentContext context) {
+ context.put(id, this);
+ before(context.getKey(), context.getReference());
+ }
+
+ @Override
+ public void after(final AgentContext context, final Object result, final Throwable error) {
+ final ConfigurableListener listener = context.get(id, ConfigurableListener.class);
+ if (listener != null) {
+ if (error != null) {
+ listener.onSuccess(context.getKey(), context.getReference(), result);
+ } else {
+ listener.onError(context.getKey(), context.getReference(), error);
+ }
+ }
+ }
+
+ @Override
+ public boolean accept(final Counter.Key key, final Object instance) {
+ final String name = key.getName();
+ return includes.matches(name) && !excludes.matches(name);
+ }
+
+ // @AutoSet should be added to children
+ public void setIncludes(final String includes) {
+ this.includes = new PredicateEvaluator(includes, ",");
+ }
+
+ // @AutoSet should be added to children
+ public void setExcludes(final String excludes) {
+ this.excludes = new PredicateEvaluator(excludes, ",");
+ }
+}
Modified: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/CounterListener.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/CounterListener.java?rev=1545708&r1=1545707&r2=1545708&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/CounterListener.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/CounterListener.java Tue Nov 26 16:16:29 2013
@@ -55,7 +55,7 @@ public class CounterListener extends Abs
}
@Override
- public void after(final AgentContext context, final Throwable error) {
+ public void after(final AgentContext context, final Object result, final Throwable error) {
final Context perfCtx = context.get(KEY, Context.class);
if (error == null) {
perfCtx.stop();
Modified: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/InvocationListener.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/InvocationListener.java?rev=1545708&r1=1545707&r2=1545708&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/InvocationListener.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/InvocationListener.java Tue Nov 26 16:16:29 2013
@@ -21,6 +21,6 @@ import org.apache.sirona.javaagent.Agent
public interface InvocationListener {
void before(AgentContext context);
- void after(AgentContext context, Throwable error);
+ void after(AgentContext context, Object result, Throwable error);
boolean accept(Counter.Key key, Object instance);
}
Modified: incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java?rev=1545708&r1=1545707&r2=1545708&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/sirona/javaagent/JavaAgentRunner.java Tue Nov 26 16:16:29 2013
@@ -123,7 +123,7 @@ public class JavaAgentRunner extends Blo
private static String[] buildProcessArgs(final FrameworkMethod mtd) throws IOException {
final Collection<String> args = new ArrayList<String>();
args.add(findJava());
- args.add("-javaagent:" + buildJavaagent() + "=excludes=regex:org.apache.test.*Test" /*+ "=includes=regex:org.apache.test.sirona.*Transform"*/);
+ args.add("-javaagent:" + buildJavaagent() + "=excludes=regex:org.apache.test.*Test,prefix:org.junit,prefix:junit" /*+ "=includes=regex:org.apache.test.sirona.*Transform"*/);
if (Boolean.getBoolean("test.debug.remote")) {
args.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005");
}
Modified: incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/AgentPerfInterceptorAgentContractTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/AgentPerfInterceptorAgentContractTest.java?rev=1545708&r1=1545707&r2=1545708&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/AgentPerfInterceptorAgentContractTest.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/AgentPerfInterceptorAgentContractTest.java Tue Nov 26 16:16:29 2013
@@ -36,7 +36,7 @@ public class AgentPerfInterceptorAgentCo
public void start() {
final Counter.Key key = AgentContext.key("start");
final AgentContext context = AgentContext.startOn(key, null);
- context.stop();
+ context.stop(null);
assertEquals("org.apache.sirona.javaagent.AgentContext", context.getClass().getName());
assertEquals(1, Repository.INSTANCE.getCounter(key).getHits());
}
@@ -46,7 +46,7 @@ public class AgentPerfInterceptorAgentCo
final Counter.Key key = AgentContext.key("ref");
final Object instance = new Object();
final AgentContext context = AgentContext.startOn(key, instance);
- context.stop();
+ context.stop(null);
assertEquals(instance, context.getReference());
assertEquals(key, context.getKey());
assertEquals(1, Repository.INSTANCE.getCounter(key).getHits());
Added: incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/HttpUrlConnectionAddHeaderTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/HttpUrlConnectionAddHeaderTest.java?rev=1545708&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/HttpUrlConnectionAddHeaderTest.java (added)
+++ incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/HttpUrlConnectionAddHeaderTest.java Tue Nov 26 16:16:29 2013
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.test.sirona.javaagent;
+
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.javaagent.AgentContext;
+import org.apache.sirona.javaagent.JavaAgentRunner;
+import org.apache.sirona.javaagent.spi.InvocationListener;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(JavaAgentRunner.class)
+public class HttpUrlConnectionAddHeaderTest {
+ @Test
+ public void addHeader() throws IOException {
+ final URLConnection connection = ConnectionFactory.createConnection();
+ try {
+ connection.connect();
+ } catch (final Exception e) {
+ // we don't care if the connection fails
+ } finally {
+ try {
+ HttpURLConnection.class.cast(connection).disconnect();
+ } catch (final Exception e) {
+ // no-op
+ }
+ }
+
+ assertEquals("sirona", connection.getRequestProperty("origin-test"));
+ }
+
+ // we can't do it on JVm classes directly ATM (sun HttpURLConnection) so using another abstraction
+ public static class ConnectionFactory {
+ private ConnectionFactory() {
+ // no-op
+ }
+
+ private static URLConnection createConnection() throws IOException {
+ final URL url = new URL("http://doesntexist:12354");
+ final URLConnection connection = url.openConnection();
+ connection.setConnectTimeout(200);
+ connection.setReadTimeout(100);
+ return connection;
+ }
+ }
+
+ public static class HttpUrlConnectionHeaderAdder implements InvocationListener {
+ @Override
+ public void before(final AgentContext context) {
+ // no-op
+ }
+
+ @Override
+ public void after(final AgentContext context, final Object result, final Throwable error) {
+ HttpURLConnection.class.cast(result).setRequestProperty("origin-test", "sirona");
+ }
+
+ @Override
+ public boolean accept(final Counter.Key key, final Object instance) { // static => instance == null
+ return key.getName().equals("org.apache.test.sirona.javaagent.HttpUrlConnectionAddHeaderTest$ConnectionFactory.createConnection");
+ }
+ }
+}
Modified: incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/IncludeExcludeTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/IncludeExcludeTest.java?rev=1545708&r1=1545707&r2=1545708&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/IncludeExcludeTest.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/IncludeExcludeTest.java Tue Nov 26 16:16:29 2013
@@ -17,8 +17,11 @@
package org.apache.test.sirona.javaagent;
import org.apache.sirona.javaagent.SironaAgent;
+import org.junit.BeforeClass;
import org.junit.Test;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
@@ -30,6 +33,18 @@ import static org.junit.Assert.assertNot
import static org.junit.Assert.fail;
public class IncludeExcludeTest {
+ private static PrintStream err;
+
+ @BeforeClass
+ public static void noDebug() {
+ System.setProperty("sirona.agent.debug", "false");
+ }
+
+ @BeforeClass
+ public static void resetDebug() {
+ System.clearProperty("sirona.agent.debug");
+ }
+
@Test
public void include() throws IllegalClassFormatException {
final InstrumentationForTestPurpose instrumentation = new InstrumentationForTestPurpose();
Added: incubator/sirona/trunk/agent/javaagent/src/test/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/test/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener?rev=1545708&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/test/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener (added)
+++ incubator/sirona/trunk/agent/javaagent/src/test/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener Tue Nov 26 16:16:29 2013
@@ -0,0 +1 @@
+org.apache.test.sirona.javaagent.HttpUrlConnectionAddHeaderTest$HttpUrlConnectionHeaderAdder