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/25 17:04:33 UTC

svn commit: r1545329 - in /incubator/sirona/trunk/agent: javaagent/src/main/java/org/apache/sirona/javaagent/ javaagent/src/main/java/org/apache/sirona/javaagent/listener/ javaagent/src/main/java/org/apache/sirona/javaagent/spi/ javaagent/src/main/reso...

Author: rmannibucau
Date: Mon Nov 25 16:04:33 2013
New Revision: 1545329

URL: http://svn.apache.org/r1545329
Log:
adding InvocationListener in javaagent

Added:
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java
      - copied, changed from r1545306, incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/
    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/
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/InvocationListener.java
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/Order.java
    incubator/sirona/trunk/agent/javaagent/src/main/resources/
    incubator/sirona/trunk/agent/javaagent/src/main/resources/META-INF/
    incubator/sirona/trunk/agent/javaagent/src/main/resources/META-INF/services/
    incubator/sirona/trunk/agent/javaagent/src/main/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener
Removed:
    incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java
Modified:
    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/test/java/org/apache/test/sirona/javaagent/AgentPerfInterceptorAgentContractTest.java
    incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java
    incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java

Copied: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java (from r1545306, incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java)
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java?p2=incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java&p1=incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java&r1=1545306&r2=1545329&rev=1545329&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentPerformanceInterceptor.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/AgentContext.java Mon Nov 25 16:04:33 2013
@@ -17,15 +17,30 @@
 package org.apache.sirona.javaagent;
 
 import org.apache.sirona.Role;
-import org.apache.sirona.aop.AbstractPerformanceInterceptor;
 import org.apache.sirona.counters.Counter;
-import org.apache.sirona.stopwatches.StopWatch;
+import org.apache.sirona.javaagent.spi.InvocationListener;
+import org.apache.sirona.javaagent.spi.Order;
+import org.apache.sirona.spi.SPI;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 // just a helper to ease ASM work and reuse AbstractPerformanceInterceptor logic
-public class AgentPerformanceInterceptor extends AbstractPerformanceInterceptor<Counter.Key> {
+public class AgentContext {
+    private static final InvocationListener[] EXISTING_LISTENERS = loadAllListeners();
+
+    private static final ConcurrentMap<Counter.Key, InvocationListener[]> LISTENERS_BY_KEY = new ConcurrentHashMap<Counter.Key, InvocationListener[]>();
+
     // called by agent
-    public static Context start(final Counter.Key key) {
-        return new AgentPerformanceInterceptor().before(key, key.getName());
+    public static AgentContext startOn(final Counter.Key key, final Object that) {
+        return new AgentContext(key, that, listeners(key, that));
     }
 
     // helper to init keys in javaagent
@@ -33,53 +48,105 @@ public class AgentPerformanceInterceptor
         return new Counter.Key(Role.PERFORMANCES, name);
     }
 
-    @Override
-    protected Counter.Key getKey(final Counter.Key key, final String name) {
-        return key;
+    private static InvocationListener[] loadAllListeners() {
+        final Collection<InvocationListener> listeners = new LinkedList<InvocationListener>();
+        for (final InvocationListener listener : SPI.INSTANCE.find(InvocationListener.class, AgentContext.class.getClassLoader())) {
+            listeners.add(listener);
+        }
+        return listeners.toArray(new InvocationListener[listeners.size()]);
     }
 
-    @Override
-    protected String getCounterName(final Counter.Key invocation) {
-        return invocation.getName();
+    private static InvocationListener[] listeners(final Counter.Key key, final Object that) {
+        InvocationListener[] listeners = LISTENERS_BY_KEY.get(key);
+        if (listeners == null) {
+            listeners = findListeners(key, that);
+            final InvocationListener[] old = LISTENERS_BY_KEY.putIfAbsent(key, listeners);
+            if (old != null) {
+                listeners = old;
+            }
+        }
+        return listeners;
     }
 
-    @Override
-    protected Object extractContextKey(final Counter.Key invocation) {
-        return invocation;
+    private static InvocationListener[] findListeners(final Counter.Key key, final Object that) {
+        final List<InvocationListener> listeners = new LinkedList<InvocationListener>();
+        for (final InvocationListener listener : EXISTING_LISTENERS) {
+            if (listener.accept(key, that)) {
+                listeners.add(listener);
+            }
+        }
+        Collections.sort(listeners, ListenerComparator.INSTANCE);
+        return listeners.toArray(new InvocationListener[listeners.size()]);
     }
 
-    @Override
-    protected ActivationContext getOrCreateContext(final Object m) {
-        final ActivationContext c = CONTEXTS.get(m);
-        if (c == null) {
-            return putAndGetActivationContext(m, new ActivationContext(true, Counter.Key.class.cast(m).getName()));
+    private final Counter.Key key;
+    private final Object reference;
+    private final InvocationListener[] listeners;
+    private final boolean hasListeners;
+    private final Map<Integer, Object> context = new HashMap<Integer, Object>();
+
+    public AgentContext(final Counter.Key key, final Object that, final InvocationListener[] listeners) {
+        this.key = key;
+        this.reference = that;
+        this.listeners = listeners;
+        this.hasListeners = listeners.length > 0;
+        if (this.hasListeners) {
+            for (final InvocationListener listener : listeners) {
+                listener.before(this);
+            }
         }
-        return c;
     }
 
-    @Override
-    protected Context newContext(final ActivationContext context, final StopWatch stopwatch) {
-        return new AgentContext(context, stopwatch);
+    public Object getReference() {
+        return reference;
+    }
+
+    public Counter.Key getKey() {
+        return key;
+    }
+
+    public <T> T get(final Integer key, final Class<T> clazz) {
+        return clazz.cast(context.get(key));
     }
 
-    @Override
-    protected Object proceed(final Counter.Key invocation) throws Throwable {
-        throw new UnsupportedOperationException("shouldn't be called directly");
+    public void put(final int key, Object data) {
+        context.put(key, data);
     }
 
-    protected static class AgentContext extends Context {
-        protected AgentContext(final ActivationContext activationContext, final StopWatch stopWatch) {
-            super(activationContext, stopWatch);
+    public void stop() {
+        stopListeners(null);
+    }
+
+    public void stopWithException(final Throwable error) {
+        stopListeners(error);
+    }
+
+    private void stopListeners(final Throwable error) {
+        if (hasListeners) {
+            for (final InvocationListener listener : listeners) {
+                listener.after(this, error);
+            }
         }
+    }
 
-        @Override
-        public void stop() {
-            super.stop();
+    private static class ListenerComparator implements Comparator<InvocationListener> {
+        private static final ListenerComparator INSTANCE = new ListenerComparator();
+
+        private ListenerComparator() {
+            // no-op
         }
 
         @Override
-        public void stopWithException(final Throwable error) {
-            super.stopWithException(error);
+        public int compare(final InvocationListener o1, final InvocationListener o2) {
+            final Order order1 = o1.getClass().getAnnotation(Order.class);
+            final Order order2 = o2.getClass().getAnnotation(Order.class);
+            if (order2 == null) {
+                return -1;
+            }
+            if (order1 == null) {
+                return 1;
+            }
+            return order1.value() - order2.value();
         }
     }
 }

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=1545329&r1=1545328&r2=1545329&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 Mon Nov 25 16:04:33 2013
@@ -65,7 +65,12 @@ public class SironaAgent {
             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);
+            try {
+                reader.accept(advisor, ClassReader.SKIP_DEBUG);
+            } catch (final RuntimeException re) {
+                re.printStackTrace(); // log it otherwise hard to know if it fails
+                throw re;
+            }
             return writer.toByteArray();
         }
 

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=1545329&r1=1545328&r2=1545329&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 Mon Nov 25 16:04:33 2013
@@ -16,7 +16,6 @@
  */
 package org.apache.sirona.javaagent;
 
-import org.apache.sirona.aop.AbstractPerformanceInterceptor;
 import org.apache.sirona.counters.Counter;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
@@ -44,7 +43,7 @@ public class SironaClassVisitor extends 
     private static final String STATIC_CLINT_MERGE_PREFIX = "_$_$irona_static_merge";
 
     private static final Type KEY_TYPE = Type.getType(Counter.Key.class);
-    private static final Type AGENT_COUNTER = Type.getType(AgentPerformanceInterceptor.class);
+    private static final Type AGENT_CONTEXT = Type.getType(AgentContext.class);
 
     private final String javaName;
     private final Map<String, String> keys = new HashMap<String, String>();
@@ -134,19 +133,20 @@ public class SironaClassVisitor extends 
 
             for (final Map.Entry<String, String> key : keys.entrySet()) {
                 push(key.getValue());
-                invokeStatic(AGENT_COUNTER, new Method(KEY_METHOD, "(" + STRING_TYPE + ")" + KEY_TYPE));
+                invokeStatic(AGENT_CONTEXT, new Method(KEY_METHOD, "(" + STRING_TYPE + ")" + KEY_TYPE));
                 putStatic(clazz, key.getKey(), KEY_TYPE);
             }
         }
     }
 
     private static class ProxyMethodsVisitor extends GeneratorAdapter {
-        private static final Type CONTEXT_TYPE = Type.getType(AbstractPerformanceInterceptor.Context.class);
         private static final Type THROWABLE_TYPE = Type.getType(Throwable.class);
-        private static final String CONTEXT_NAME = CONTEXT_TYPE.getDescriptor();
+        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[] START_ARGS_TYPES = new Type[]{ KEY_TYPE, OBJECT_TYPE };
 
         // methods
-        private static final String START_METHOD = "start";
+        private static final String START_METHOD = "startOn";
         private static final String STOP_WITH_EXCEPTION_METHOD = "stopWithException";
         private static final String STOP_METHOD = "stop";
 
@@ -166,9 +166,14 @@ public class SironaClassVisitor extends 
 
         @Override
         public void visitCode() {
-            final int agentIdx = newLocal(CONTEXT_TYPE);
+            final int agentIdx = newLocal(AGENT_CONTEXT);
             getStatic(clazz, method.getName() + FIELD_SUFFIX, KEY_TYPE);
-            invokeStatic(AGENT_COUNTER, new Method(START_METHOD, "(" + KEY_TYPE + ")" + CONTEXT_NAME));
+            if (!isStatic) {
+                loadThis();
+            } else {
+                visitInsn(ACONST_NULL); // this == null for static methods
+            }
+            invokeStatic(AGENT_CONTEXT, new Method(START_METHOD, AGENT_CONTEXT, START_ARGS_TYPES));
             storeLocal(agentIdx);
 
             final Label tryStart = mark();
@@ -180,7 +185,7 @@ public class SironaClassVisitor extends 
 
             // take metrics before returning
             loadLocal(agentIdx);
-            invokeVirtual(CONTEXT_TYPE, new Method(STOP_METHOD, NO_PARAM_RETURN_VOID));
+            invokeVirtual(AGENT_CONTEXT, new Method(STOP_METHOD, NO_PARAM_RETURN_VOID));
 
             // return result
             returnResult(result);
@@ -193,7 +198,7 @@ public class SironaClassVisitor extends 
             storeLocal(throwableId);
             loadLocal(agentIdx);
             loadLocal(throwableId);
-            invokeVirtual(CONTEXT_TYPE, new Method(STOP_WITH_EXCEPTION_METHOD, Type.getType(Void.TYPE), new Type[]{THROWABLE_TYPE}));
+            invokeVirtual(AGENT_CONTEXT, new Method(STOP_WITH_EXCEPTION_METHOD, Type.VOID_TYPE, STOP_WITH_THROWABLE_ARGS_TYPES));
 
             // rethrow throwable
             loadLocal(throwableId);

Added: 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=1545329&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/CounterListener.java (added)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/listener/CounterListener.java Mon Nov 25 16:04:33 2013
@@ -0,0 +1,80 @@
+/*
+ * 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.aop.AbstractPerformanceInterceptor;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.javaagent.AgentContext;
+import org.apache.sirona.javaagent.spi.InvocationListener;
+
+public class CounterListener extends AbstractPerformanceInterceptor<Counter.Key> implements InvocationListener {
+    private static final int KEY = 0;
+
+    @Override // TODO: add config here?
+    public boolean accept(final Counter.Key key, final Object instance) {
+        return true;
+    }
+
+    @Override
+    public void before(final AgentContext ctx) {
+        final Counter.Key key = ctx.getKey();
+        ctx.put(KEY, new CounterListener().before(key, key.getName()));
+    }
+
+    @Override
+    public void after(final AgentContext context, final Throwable error) {
+        final Context perfCtx = context.get(KEY, Context.class);
+        if (error == null) {
+            perfCtx.stop();
+        } else {
+            perfCtx.stopWithException(error);
+        }
+    }
+
+    @Override
+    protected Counter.Key getKey(final Counter.Key key, final String name) {
+        return key;
+    }
+
+    @Override
+    protected String getCounterName(final Counter.Key invocation) {
+        return invocation.getName();
+    }
+
+    @Override
+    protected Object extractContextKey(final Counter.Key invocation) {
+        return invocation;
+    }
+
+    @Override
+    protected ActivationContext getOrCreateContext(final Object m) {
+        final ActivationContext c = CONTEXTS.get(m);
+        if (c == null) {
+            return putAndGetActivationContext(m, new ActivationContext(true, Counter.Key.class.cast(m).getName()));
+        }
+        return c;
+    }
+
+    @Override
+    protected Object proceed(final Counter.Key invocation) throws Throwable {
+        return unsupportedOperation();
+    }
+
+    private static <T> T unsupportedOperation() {
+        throw new UnsupportedOperationException("shouldn't be called directly");
+    }
+}

Added: 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=1545329&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/InvocationListener.java (added)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/InvocationListener.java Mon Nov 25 16:04:33 2013
@@ -0,0 +1,27 @@
+/*
+ * 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.spi;
+
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.javaagent.AgentContext;
+
+@Order(0)
+public interface InvocationListener {
+    void before(AgentContext context);
+    void after(AgentContext context, Throwable error);
+    boolean accept(Counter.Key key, Object instance);
+}

Added: incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/Order.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/Order.java?rev=1545329&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/Order.java (added)
+++ incubator/sirona/trunk/agent/javaagent/src/main/java/org/apache/sirona/javaagent/spi/Order.java Mon Nov 25 16:04:33 2013
@@ -0,0 +1,28 @@
+/*
+ * 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.spi;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Order {
+    int value();
+}

Added: incubator/sirona/trunk/agent/javaagent/src/main/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/main/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener?rev=1545329&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/main/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener (added)
+++ incubator/sirona/trunk/agent/javaagent/src/main/resources/META-INF/services/org.apache.sirona.javaagent.spi.InvocationListener Mon Nov 25 16:04:33 2013
@@ -0,0 +1 @@
+org.apache.sirona.javaagent.listener.CounterListener

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=1545329&r1=1545328&r2=1545329&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 Mon Nov 25 16:04:33 2013
@@ -17,9 +17,8 @@
 package org.apache.test.sirona.javaagent;
 
 import org.apache.sirona.Role;
-import org.apache.sirona.aop.AbstractPerformanceInterceptor;
 import org.apache.sirona.counters.Counter;
-import org.apache.sirona.javaagent.AgentPerformanceInterceptor;
+import org.apache.sirona.javaagent.AgentContext;
 import org.apache.sirona.repositories.Repository;
 import org.junit.Test;
 
@@ -28,17 +27,28 @@ import static org.junit.Assert.assertEqu
 public class AgentPerfInterceptorAgentContractTest {
     @Test
     public void key() {
-        final Counter.Key key = AgentPerformanceInterceptor.key("key");
+        final Counter.Key key = AgentContext.key("key");
         assertEquals(Role.PERFORMANCES, key.getRole());
         assertEquals("key", key.getName());
     }
 
     @Test
     public void start() {
-        final Counter.Key key = AgentPerformanceInterceptor.key("start");
-        final AbstractPerformanceInterceptor.Context context = AgentPerformanceInterceptor.start(key);
+        final Counter.Key key = AgentContext.key("start");
+        final AgentContext context = AgentContext.startOn(key, null);
         context.stop();
-        assertEquals("org.apache.sirona.javaagent.AgentPerformanceInterceptor$AgentContext", context.getClass().getName());
+        assertEquals("org.apache.sirona.javaagent.AgentContext", context.getClass().getName());
+        assertEquals(1, Repository.INSTANCE.getCounter(key).getHits());
+    }
+
+    @Test
+    public void attributes() {
+        final Counter.Key key = AgentContext.key("ref");
+        final Object instance = new Object();
+        final AgentContext context = AgentContext.startOn(key, instance);
+        context.stop();
+        assertEquals(instance, context.getReference());
+        assertEquals(key, context.getKey());
         assertEquals(1, Repository.INSTANCE.getCounter(key).getHits());
     }
 }

Modified: incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java?rev=1545329&r1=1545328&r2=1545329&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java (original)
+++ incubator/sirona/trunk/agent/javaagent/src/test/java/org/apache/test/sirona/javaagent/SimpleTest.java Mon Nov 25 16:04:33 2013
@@ -56,6 +56,13 @@ public class SimpleTest {
     }
 
     @Test
+    public void staticMethod() {
+        assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.staticMethod", 0);
+        ServiceTransform.staticMethod();
+        assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.staticMethod", 1);
+    }
+
+    @Test
     public void nested() {
         assertHits("org.apache.test.sirona.javaagent.SimpleTest$ServiceTransform.nest", 0);
         assertHits("org.apache.test.sirona.javaagent.SimpleTest$Service2Transform.nested", 0);
@@ -110,6 +117,10 @@ public class SimpleTest {
             // no-op
         }
 
+        public static String staticMethod() {
+            return "ok";
+        }
+
         public String withReturn() {
             return "ok";
         }

Modified: incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java?rev=1545329&r1=1545328&r2=1545329&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java (original)
+++ incubator/sirona/trunk/agent/performance/aop/src/main/java/org/apache/sirona/aop/AbstractPerformanceInterceptor.java Mon Nov 25 16:04:33 2013
@@ -100,16 +100,20 @@ public abstract class AbstractPerformanc
 
         final StopWatch stopwatch;
         if (context.shouldExecute()) {
-            final Counter monitor = Repository.INSTANCE.getCounter(getKey(name));
+            final Counter monitor = Repository.INSTANCE.getCounter(getKey(invocation, name));
             stopwatch = Repository.INSTANCE.start(monitor);
         } else {
             stopwatch = null;
         }
 
+        return newContext(invocation, context, stopwatch);
+    }
+
+    protected Context newContext(final T invocation, final ActivationContext context, final StopWatch stopwatch) {
         return new Context(context, stopwatch);
     }
 
-    protected Counter.Key getKey(final String name) {
+    protected Counter.Key getKey(final T invocation, final String name) {
         return new Counter.Key(getRole(), name);
     }
 
@@ -182,8 +186,8 @@ public abstract class AbstractPerformanc
      * The handler for cases where interception is not possible and you need to pass the "before"object to be able to monitor.
      */
     public static class Context {
-        private final ActivationContext activationContext;
-        private final StopWatch stopWatch;
+        protected final ActivationContext activationContext;
+        protected final StopWatch stopWatch;
 
         public Context(final ActivationContext activationContext, final StopWatch stopWatch) {
             this.activationContext = activationContext;