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/05 18:25:24 UTC

svn commit: r1539076 [3/17] - in /incubator/sirona/trunk: ./ agent/ agent/performance/ agent/performance/aop/ agent/performance/aop/src/ agent/performance/aop/src/main/ agent/performance/aop/src/main/java/ agent/performance/aop/src/main/java/org/ agent...

Added: incubator/sirona/trunk/agent/performance/jpa/src/test/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jpa/src/test/resources/META-INF/persistence.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jpa/src/test/resources/META-INF/persistence.xml (added)
+++ incubator/sirona/trunk/agent/performance/jpa/src/test/resources/META-INF/persistence.xml Tue Nov  5 17:25:15 2013
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+  -->
+<persistence version="2.0"
+             xmlns="http://java.sun.com/xml/ns/persistence"
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
+                       http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
+  <persistence-unit name="test-jse" transaction-type="RESOURCE_LOCAL">
+    <provider>org.apache.sirona.jpa.MonitoringPersistence</provider>
+    <class>org.apache.sirona.jpa.entity.Person</class>
+    <class>org.apache.sirona.jpa.entity.Address</class>
+    <properties>
+      <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+      <property name="openjpa.ConnectionURL" value="jdbc:hsqldb:mem:jpa;create=true"/>
+      <property name="openjpa.ConnectionDriverName" value="org.hsqldb.jdbcDriver"/>
+      <property name="openjpa.ConnectionUserName" value="sa"/>
+      <property name="openjpa.ConnectionPassword" value=""/>
+      <property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO, SQL=INFO"/>
+    </properties>
+  </persistence-unit>
+  <persistence-unit name="test-jta">
+    <provider>org.apache.sirona.jpa.MonitoringPersistence</provider>
+    <class>org.apache.sirona.jpa.entity.Person</class>
+    <class>org.apache.sirona.jpa.entity.Address</class>
+    <properties>
+      <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+      <property name="openjpa.ConnectionURL" value="jdbc:hsqldb:mem:jpa;create=true"/>
+      <property name="openjpa.ConnectionDriverName" value="org.hsqldb.jdbcDriver"/>
+      <property name="openjpa.ConnectionUserName" value="sa"/>
+      <property name="openjpa.ConnectionPassword" value=""/>
+      <property name="openjpa.RuntimeUnenhancedClasses" value="supported"/>
+      <property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO, SQL=INFO"/>
+    </properties>
+  </persistence-unit>
+</persistence>

Added: incubator/sirona/trunk/agent/performance/jta/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jta/pom.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jta/pom.xml (added)
+++ incubator/sirona/trunk/agent/performance/jta/pom.xml Tue Nov  5 17:25:15 2013
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>sirona-performance</artifactId>
+    <groupId>org.apache.sirona</groupId>
+    <version>0.1-incubating-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>sirona-jta</artifactId>
+  <name>Apache Sirona Incubator :: Agent :: Performance  :: JTA</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jta_1.1_spec</artifactId>
+      <version>1.1.1</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+      <version>1.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+      <version>1.0</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.sirona</groupId>
+      <artifactId>sirona-core</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.openejb</groupId>
+      <artifactId>openejb-core</artifactId>
+      <version>4.5.2</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>

Added: incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAGauges.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAGauges.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAGauges.java (added)
+++ incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAGauges.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,83 @@
+/*
+ * 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.jta;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.configuration.Configuration;
+import org.apache.sirona.counters.Unit;
+import org.apache.sirona.gauges.Gauge;
+import org.apache.sirona.gauges.GaugeFactory;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public class JTAGauges implements GaugeFactory {
+    public static final Role JTA_COMMITED = new Role("jta-commited", Unit.UNARY);
+    public static final Role JTA_ROLLBACKED = new Role("jta-rollbacked", Unit.UNARY);
+    public static final Role JTA_ACTIVE = new Role("jta-active", Unit.UNARY);
+
+    static final AtomicLong ACTIVE = new AtomicLong(0);
+    static final AtomicLong COMMITTED = new AtomicLong(0);
+    static final AtomicLong ROLLBACKED = new AtomicLong(0);
+
+    @Override
+    public Gauge[] gauges() {
+        final long period = Configuration.getInteger(Configuration.CONFIG_PROPERTY_PREFIX + "gauge.jta.period", 4000);
+        return new Gauge[] {
+            new JTAGauge(JTA_COMMITED, COMMITTED, period),
+            new JTAGauge(JTA_ROLLBACKED, ROLLBACKED, period),
+            new JTAActiveGauge(JTA_ACTIVE, ACTIVE, period)
+        };
+    }
+
+    protected static class JTAGauge implements Gauge {
+        private final Role role;
+        private final long period;
+        protected final AtomicLong counter;
+
+        protected JTAGauge(final Role role, final AtomicLong counter, final long period) {
+            this.role = role;
+            this.counter = counter;
+            this.period = period;
+        }
+
+        @Override
+        public Role role() {
+            return role;
+        }
+
+        @Override
+        public double value() {
+            return counter.getAndSet(0);
+        }
+
+        @Override
+        public long period() {
+            return period;
+        }
+    }
+
+    protected static class JTAActiveGauge extends JTAGauge {
+        protected JTAActiveGauge(final Role role, final AtomicLong counter, final long period) {
+            super(role, counter, period);
+        }
+
+        @Override
+        public double value() {
+            return counter.get();
+        }
+    }
+}

Added: incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAInterceptor.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAInterceptor.java (added)
+++ incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAInterceptor.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,64 @@
+/*
+ * 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.jta;
+
+import javax.annotation.Resource;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.AroundTimeout;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.TransactionSynchronizationRegistry;
+
+@Interceptor
+@JTAMonitored
+public class JTAInterceptor {
+    private static final String RESOURCE_KEY = JTAInterceptor.class.getName();
+
+    @Resource
+    private TransactionSynchronizationRegistry transactionSynchronizationRegistry;
+
+    @AroundInvoke
+    @AroundTimeout
+    public Object jta(final InvocationContext invocationContext) throws Throwable {
+        if (transactionSynchronizationRegistry.getTransactionStatus() == Status.STATUS_ACTIVE
+                && transactionSynchronizationRegistry.getResource(RESOURCE_KEY) == null) {
+            JTAGauges.ACTIVE.incrementAndGet();
+            transactionSynchronizationRegistry.putResource(RESOURCE_KEY, Boolean.TRUE);
+            transactionSynchronizationRegistry.registerInterposedSynchronization(new JTACounterSynchronization());
+        }
+        return invocationContext.proceed();
+    }
+
+    private static class JTACounterSynchronization implements Synchronization {
+        @Override
+        public void beforeCompletion() {
+            // no-op
+        }
+
+        @Override
+        public void afterCompletion(final int status) {
+            if (status == Status.STATUS_COMMITTED) {
+                JTAGauges.COMMITTED.incrementAndGet();
+            } else if (status == Status.STATUS_ROLLEDBACK) {
+                JTAGauges.ROLLBACKED.incrementAndGet();
+            }
+            JTAGauges.ACTIVE.decrementAndGet();
+        }
+    }
+}

Added: incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAMonitored.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAMonitored.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAMonitored.java (added)
+++ incubator/sirona/trunk/agent/performance/jta/src/main/java/org/apache/sirona/jta/JTAMonitored.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,29 @@
+/*
+ * 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.jta;
+
+import javax.interceptor.InterceptorBinding;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@InterceptorBinding
+@Target({ElementType.TYPE, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JTAMonitored {
+}

Added: incubator/sirona/trunk/agent/performance/jta/src/main/resources/META-INF/beans.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jta/src/main/resources/META-INF/beans.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jta/src/main/resources/META-INF/beans.xml (added)
+++ incubator/sirona/trunk/agent/performance/jta/src/main/resources/META-INF/beans.xml Tue Nov  5 17:25:15 2013
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
+                            http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+  <interceptors>
+    <class>org.apache.sirona.jta.JTAInterceptor</class>
+  </interceptors>
+</beans>

Added: incubator/sirona/trunk/agent/performance/jta/src/main/resources/META-INF/services/org.apache.sirona.gauges.GaugeFactory
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jta/src/main/resources/META-INF/services/org.apache.sirona.gauges.GaugeFactory?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jta/src/main/resources/META-INF/services/org.apache.sirona.gauges.GaugeFactory (added)
+++ incubator/sirona/trunk/agent/performance/jta/src/main/resources/META-INF/services/org.apache.sirona.gauges.GaugeFactory Tue Nov  5 17:25:15 2013
@@ -0,0 +1 @@
+org.apache.sirona.jta.JTAGauges

Added: incubator/sirona/trunk/agent/performance/jta/src/test/java/org/apache/sirona/jta/GaugesTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jta/src/test/java/org/apache/sirona/jta/GaugesTest.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jta/src/test/java/org/apache/sirona/jta/GaugesTest.java (added)
+++ incubator/sirona/trunk/agent/performance/jta/src/test/java/org/apache/sirona/jta/GaugesTest.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,121 @@
+/*
+ * 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.jta;
+
+import org.apache.sirona.gauges.Gauge;
+import org.apache.sirona.repositories.Repository;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.ejb.EJB;
+import javax.ejb.Lock;
+import javax.ejb.LockType;
+import javax.ejb.Singleton;
+import javax.ejb.embeddable.EJBContainer;
+import java.util.Collection;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.junit.Assert.assertEquals;
+
+public class GaugesTest {
+    private static final int ITERATIONS = 500;
+
+    private static Gauge.LoaderHelper gaugeLoader;
+
+    @BeforeClass
+    public static void init() {
+        Repository.INSTANCE.clear();
+        gaugeLoader = new Gauge.LoaderHelper(false);
+    }
+
+    @AfterClass
+    public static void reset() {
+        Repository.INSTANCE.clear();
+        gaugeLoader.destroy();
+    }
+
+    @EJB
+    private EjbWithJTASupport jtaSupport;
+
+    @Test
+    public void test() throws Exception {
+        final EJBContainer container = EJBContainer.createEJBContainer();
+        container.getContext().bind("inject", this);
+
+        final long start = System.currentTimeMillis();
+
+        final CountDownLatch latch = new CountDownLatch(ITERATIONS);
+        try {
+            final ExecutorService es = Executors.newFixedThreadPool(50);
+            for (int i = 0; i < ITERATIONS; i++) {
+                es.submit(new Runnable() {
+                    @Override
+                    public void run() {
+                        jtaSupport.commit();
+                        try {
+                            jtaSupport.rollback();
+                        } finally {
+                            latch.countDown();
+                        }
+                    }
+                });
+            }
+            es.shutdown();
+            latch.await();
+
+            Thread.sleep(500); // wait last measure
+
+            final long end = System.currentTimeMillis();
+
+            assertEquals(ITERATIONS, sum(Repository.INSTANCE.getGaugeValues(start, end, JTAGauges.JTA_COMMITED).values()), 0);
+            assertEquals(ITERATIONS, sum(Repository.INSTANCE.getGaugeValues(start, end, JTAGauges.JTA_ROLLBACKED).values()), 0);
+
+            // due to the sleep we use in commit() we only see half of the tx when checking actives
+            assertEquals(ITERATIONS / 2, sum(Repository.INSTANCE.getGaugeValues(start, end, JTAGauges.JTA_ACTIVE).values()), ITERATIONS * .1);
+        } finally {
+            container.close();
+        }
+    }
+
+    private double sum(final Collection<Double> values) {
+        double sum = 0;
+        for (final Double d : values) {
+            sum += d;
+        }
+        return sum;
+    }
+
+    @Singleton
+    @Lock(LockType.READ)
+    @JTAMonitored
+    public static class EjbWithJTASupport {
+        public void commit() {
+            try {
+                Thread.sleep(50);
+            } catch (final InterruptedException e) {
+                // no-op
+            }
+        }
+
+        public void rollback() {
+            throw new NullPointerException();
+        }
+    }
+}

Added: incubator/sirona/trunk/agent/performance/jta/src/test/resources/sirona.properties
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/jta/src/test/resources/sirona.properties?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/jta/src/test/resources/sirona.properties (added)
+++ incubator/sirona/trunk/agent/performance/jta/src/test/resources/sirona.properties Tue Nov  5 17:25:15 2013
@@ -0,0 +1,17 @@
+# 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.
+org.apache.sirona.gauge.jta.period = 100

Added: incubator/sirona/trunk/agent/performance/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/pom.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/pom.xml (added)
+++ incubator/sirona/trunk/agent/performance/pom.xml Tue Nov  5 17:25:15 2013
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>sirona-agent</artifactId>
+    <groupId>org.apache.sirona</groupId>
+    <version>0.1-incubating-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>sirona-performance</artifactId>
+  <name>Apache Sirona Incubator :: Agent :: Performance</name>
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>aop</module>
+    <module>aspectj</module>
+    <module>cdi</module>
+    <module>jdbc</module>
+    <module>jpa</module>
+    <module>jta</module>
+    <module>spring</module>
+    <module>web</module>
+  </modules>
+</project>

Added: incubator/sirona/trunk/agent/performance/spring/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/spring/pom.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/spring/pom.xml (added)
+++ incubator/sirona/trunk/agent/performance/spring/pom.xml Tue Nov  5 17:25:15 2013
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <artifactId>sirona-performance</artifactId>
+    <groupId>org.apache.sirona</groupId>
+    <version>0.1-incubating-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>sirona-spring</artifactId>
+  <name>Apache Sirona Incubator :: Agent :: Performance  :: Spring Integration</name>
+
+  <properties>
+    <spring.version>3.2.3.RELEASE</spring.version>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-aop</artifactId>
+      <version>${spring.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sirona</groupId>
+      <artifactId>sirona-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sirona</groupId>
+      <artifactId>sirona-aop</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>aopalliance</groupId>
+      <artifactId>aopalliance</artifactId>
+      <version>1.0</version>
+      <optional>true</optional>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-context</artifactId>
+      <version>${spring.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+      <version>${spring.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file

Added: incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/AopaliancePerformanceInterceptor.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/AopaliancePerformanceInterceptor.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/AopaliancePerformanceInterceptor.java (added)
+++ incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/AopaliancePerformanceInterceptor.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,49 @@
+/*
+ * 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.spring;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.sirona.aop.AbstractPerformanceInterceptor;
+
+/**
+ * Spring-aop implementation of PerformanceInterceptor.
+ *
+ * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
+ */
+public class AopaliancePerformanceInterceptor extends AbstractPerformanceInterceptor<MethodInvocation> implements MethodInterceptor {
+    @Override
+    public Object invoke(final MethodInvocation invocation) throws Throwable {
+        return doInvoke(invocation);
+    }
+
+    @Override
+    protected String getCounterName(final MethodInvocation invocation) {
+        return getCounterName(invocation.getThis(), invocation.getMethod());
+    }
+
+    @Override
+    protected Object proceed(final MethodInvocation invocation) throws Throwable {
+        return invocation.proceed();
+    }
+
+    @Override
+    protected Object extractContextKey(final MethodInvocation invocation) {
+        return new SerializableMethod(invocation.getMethod());
+    }
+}
\ No newline at end of file

Added: incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/BeanNameMonitoringAutoProxyCreator.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/BeanNameMonitoringAutoProxyCreator.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/BeanNameMonitoringAutoProxyCreator.java (added)
+++ incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/BeanNameMonitoringAutoProxyCreator.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,45 @@
+/*
+ * 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.spring;
+
+import org.apache.sirona.aop.DefaultMonitorNameExtractor;
+import org.apache.sirona.aop.MonitorNameExtractor;
+import org.springframework.aop.TargetSource;
+import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
+
+public class BeanNameMonitoringAutoProxyCreator extends BeanNameAutoProxyCreator {
+    private MonitorNameExtractor counterNameExtractor = DefaultMonitorNameExtractor.INSTANCE;
+
+    @Override
+    protected Object[] getAdvicesAndAdvisorsForBean(final Class beanClass, final String beanName, final TargetSource targetSource) {
+        if (super.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource) != DO_NOT_PROXY) {
+            final AopaliancePerformanceInterceptor interceptor = new AopaliancePerformanceInterceptor();
+            interceptor.setMonitorNameExtractor(counterNameExtractor);
+            return new Object[] { interceptor };
+        }
+        return DO_NOT_PROXY;
+    }
+
+    public void setCounterNameExtractor(final MonitorNameExtractor counterNameExtractor) {
+        this.counterNameExtractor = counterNameExtractor;
+    }
+
+    public MonitorNameExtractor getCounterNameExtractor() {
+        return counterNameExtractor;
+    }
+}

Added: incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/PointcutMonitoringAutoProxyCreator.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/PointcutMonitoringAutoProxyCreator.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/PointcutMonitoringAutoProxyCreator.java (added)
+++ incubator/sirona/trunk/agent/performance/spring/src/main/java/org/apache/sirona/spring/PointcutMonitoringAutoProxyCreator.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,68 @@
+/*
+ * 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.spring;
+
+import org.aopalliance.aop.Advice;
+import org.apache.sirona.aop.DefaultMonitorNameExtractor;
+import org.apache.sirona.aop.MonitorNameExtractor;
+import org.springframework.aop.Advisor;
+import org.springframework.aop.Pointcut;
+import org.springframework.aop.PointcutAdvisor;
+import org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator;
+import org.springframework.aop.support.DefaultPointcutAdvisor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Creates monitored proxies for beans that match a pointcut.
+ *
+ * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
+ */
+public class PointcutMonitoringAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
+    private MonitorNameExtractor monitorNameExtractor = DefaultMonitorNameExtractor.INSTANCE;
+    private Pointcut pointcut;
+
+    @Override
+    protected List<Advisor> findCandidateAdvisors() {
+        final AopaliancePerformanceInterceptor interceptor = new AopaliancePerformanceInterceptor();
+        interceptor.setMonitorNameExtractor(monitorNameExtractor);
+
+        final PointcutAdvisor adivsor = createPointcutAdvisor(interceptor);
+
+        final List<Advisor> adivisors = new ArrayList<Advisor>(1);
+        adivisors.add(adivsor);
+        return adivisors;
+    }
+
+    protected PointcutAdvisor createPointcutAdvisor(Advice advice) {
+        return new DefaultPointcutAdvisor(pointcut, advice);
+    }
+
+    public void setMonitorNameExtractor(final MonitorNameExtractor monitorNameExtractor) {
+        this.monitorNameExtractor = monitorNameExtractor;
+    }
+
+    public void setPointcut(final Pointcut pointcut) {
+        this.pointcut = pointcut;
+    }
+
+    public MonitorNameExtractor getMonitorNameExtractor() {
+        return monitorNameExtractor;
+    }
+}

Added: incubator/sirona/trunk/agent/performance/spring/src/test/java/org/apache/sirona/spring/SpringMonitoringTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/spring/src/test/java/org/apache/sirona/spring/SpringMonitoringTest.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/spring/src/test/java/org/apache/sirona/spring/SpringMonitoringTest.java (added)
+++ incubator/sirona/trunk/agent/performance/spring/src/test/java/org/apache/sirona/spring/SpringMonitoringTest.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,42 @@
+/*
+ * 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.spring;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+import org.apache.sirona.spring.service.MyService;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration("/monitoring.xml")
+public class SpringMonitoringTest {
+    @Autowired
+    private MyService service;
+
+    @Test
+    public void checkMonitoringIsActivated() {
+        service.doIt();
+        assertEquals(1, Repository.INSTANCE.getCounter(new Counter.Key(Role.PERFORMANCES, MyService.class.getName() + ".doIt")).getHits());
+    }
+}

Added: incubator/sirona/trunk/agent/performance/spring/src/test/java/org/apache/sirona/spring/service/MyService.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/spring/src/test/java/org/apache/sirona/spring/service/MyService.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/spring/src/test/java/org/apache/sirona/spring/service/MyService.java (added)
+++ incubator/sirona/trunk/agent/performance/spring/src/test/java/org/apache/sirona/spring/service/MyService.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,23 @@
+/*
+ * 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.spring.service;
+
+public class MyService {
+    public String doIt() {
+        return "ok";
+    }
+}

Added: incubator/sirona/trunk/agent/performance/spring/src/test/resources/monitoring.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/spring/src/test/resources/monitoring.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/spring/src/test/resources/monitoring.xml (added)
+++ incubator/sirona/trunk/agent/performance/spring/src/test/resources/monitoring.xml Tue Nov  5 17:25:15 2013
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+  <bean id="service" class="org.apache.sirona.spring.service.MyService" />
+
+  <bean class="org.apache.sirona.spring.BeanNameMonitoringAutoProxyCreator">
+    <property name="beanNames">
+      <list>
+        <value>service</value>
+      </list>
+    </property>
+  </bean>
+</beans>

Added: incubator/sirona/trunk/agent/performance/web/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/pom.xml?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/pom.xml (added)
+++ incubator/sirona/trunk/agent/performance/web/pom.xml Tue Nov  5 17:25:15 2013
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <artifactId>sirona-performance</artifactId>
+    <groupId>org.apache.sirona</groupId>
+    <version>0.1-incubating-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>sirona-web</artifactId>
+  <name>Apache Sirona Incubator :: Agent :: Performance  :: Web</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jsp_2.1_spec</artifactId>
+      <version>1.0.1</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-servlet_3.0_spec</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.sirona</groupId>
+      <artifactId>sirona-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sirona</groupId>
+      <artifactId>sirona-aop</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+      <artifactId>shrinkwrap-descriptors-impl-javaee</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.shrinkwrap.resolver</groupId>
+      <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.arquillian.junit</groupId>
+      <artifactId>arquillian-junit-container</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.arquillian.protocol</groupId>
+      <artifactId>arquillian-protocol-servlet</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.arquillian.container</groupId>
+      <artifactId>arquillian-tomcat-embedded-7</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomcat.embed</groupId>
+      <artifactId>tomcat-embed-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomcat.embed</groupId>
+      <artifactId>tomcat-embed-jasper</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tomcat.embed</groupId>
+      <artifactId>tomcat-embed-logging-juli</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.eclipse.jdt.core.compiler</groupId>
+      <artifactId>ecj</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>net.sourceforge.htmlunit</groupId>
+      <artifactId>htmlunit</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/discovery/GaugeDiscoveryListener.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/discovery/GaugeDiscoveryListener.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/discovery/GaugeDiscoveryListener.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/discovery/GaugeDiscoveryListener.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,118 @@
+/*
+ * 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.web.discovery;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.configuration.Configuration;
+import org.apache.sirona.counters.Unit;
+import org.apache.sirona.gauges.Gauge;
+import org.apache.sirona.web.servlet.MonitoringFilter;
+import org.apache.sirona.web.servlet.StatusGauge;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import java.net.HttpURLConnection;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class GaugeDiscoveryListener implements ServletContextListener {
+    public static final String STATUS_GAUGES_ATTRIBUTE = "status-gauges";
+    private static final int[] DEFAULT_STATUSES = {
+        HttpURLConnection.HTTP_OK,
+        HttpURLConnection.HTTP_CREATED,
+        HttpURLConnection.HTTP_NO_CONTENT,
+        HttpURLConnection.HTTP_BAD_REQUEST,
+        HttpURLConnection.HTTP_MOVED_PERM,
+        HttpURLConnection.HTTP_MOVED_TEMP,
+        HttpURLConnection.HTTP_FORBIDDEN,
+        HttpURLConnection.HTTP_NOT_FOUND,
+        HttpURLConnection.HTTP_INTERNAL_ERROR
+    };
+
+    private Gauge.LoaderHelper helper;
+
+    @Override
+    public void contextInitialized(final ServletContextEvent sce) {
+        // init status gauges
+        final ConcurrentMap<Integer, StatusGauge> gauges = new ConcurrentHashMap<Integer, StatusGauge>(35);
+        if ("true".equalsIgnoreCase((String) sce.getServletContext().getAttribute(MonitoringFilter.MONITOR_STATUS))) {
+            final String monitoredStatuses = sce.getServletContext().getInitParameter(Configuration.CONFIG_PROPERTY_PREFIX + "web.monitored-statuses");
+
+            String contextPath = sce.getServletContext().getContextPath();
+            if (contextPath == null || contextPath.isEmpty()) {
+                contextPath = "/";
+            }
+
+            if (monitoredStatuses == null) {
+                for (final int status : DEFAULT_STATUSES) {
+                    gauges.put(status, statusGauge(contextPath, gauges, status));
+                }
+                /* we could use it but it defines 25 statuses, surely too much
+                for (final Field f : HttpURLConnection.class.getDeclaredFields()) {
+                    final int modifiers = f.getModifiers();
+                    if (f.getName().startsWith("HTTP_")
+                        && Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) && Modifier.isFinal(modifiers)) {
+                        try {
+                            final int status = (Integer) f.get(null);
+                            gauges.put(status, statusGauge(sce.getServletContext().getContextPath(), gauges, (Integer) f.get(null)));
+                        } catch (final IllegalAccessException e) {
+                            // no-op
+                        }
+                    }
+                }
+                */
+            } else {
+                for (final String status : monitoredStatuses.split(",")) {
+                    final int statusInt = Integer.parseInt(status.trim());
+                    gauges.put(statusInt, statusGauge(contextPath, gauges, statusInt));
+                }
+            }
+            sce.getServletContext().setAttribute(STATUS_GAUGES_ATTRIBUTE, gauges);
+        }
+
+        // discovery registration
+        final String prefixesStr = sce.getServletContext().getInitParameter("monitoring.discovery.packages");
+        final String[] prefixes;
+        if (prefixesStr != null) {
+            prefixes = prefixesStr.split(",");
+        } else {
+            prefixes = null;
+        }
+        helper = new Gauge.LoaderHelper("true".equals(sce.getServletContext().getInitParameter("monitoring.discovery.exclude-parent")), gauges.values(), prefixes);
+    }
+
+    @Override
+    public void contextDestroyed(final ServletContextEvent sce) {
+        if (helper != null) {
+            helper.destroy();
+        }
+    }
+
+    private static StatusGauge statusGauge(final String prefix, final ConcurrentMap<Integer, StatusGauge> gauges, final int status) {
+        final StatusGauge gauge = gauges.get(status);
+        if (gauge != null) {
+            return gauge;
+        }
+
+        final StatusGauge newGauge = new StatusGauge(new Role(prefix + "-HTTP-" + Integer.toString(status), Unit.UNARY));
+        final StatusGauge old = gauges.putIfAbsent(status, newGauge);
+        if (old != null) {
+            return old;
+        }
+        return newGauge;
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StartTag.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StartTag.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StartTag.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StartTag.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,62 @@
+/*
+ * 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.web.jsp;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+import org.apache.sirona.stopwatches.StopWatch;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import static org.apache.sirona.web.jsp.TagUtils.getScope;
+
+/**
+ * A JSP tag to counter JSP rendering performances
+ *
+ * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
+ */
+public class StartTag extends TagSupport {
+    private String id;
+    private String scope;
+    private String name;
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    @Override
+    public int doStartTag() throws JspException {
+        final StopWatch stopWatch = Repository.INSTANCE.start(Repository.INSTANCE.getCounter(new Counter.Key(Role.JSP, name)));
+        if (scope != null) {
+            pageContext.setAttribute(id, stopWatch, getScope(scope));
+        } else {
+            pageContext.setAttribute(id, stopWatch);
+        }
+        return EVAL_PAGE;
+    }
+
+    public void setScope(String scope) {
+        this.scope = scope;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StartTagTei.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StartTagTei.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StartTagTei.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StartTagTei.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,36 @@
+/*
+ * 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.web.jsp;
+
+import org.apache.sirona.stopwatches.StopWatch;
+
+import javax.servlet.jsp.tagext.TagData;
+import javax.servlet.jsp.tagext.TagExtraInfo;
+import javax.servlet.jsp.tagext.VariableInfo;
+
+/**
+ * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
+ */
+public class StartTagTei extends TagExtraInfo {
+    @Override
+    public VariableInfo[] getVariableInfo(final TagData data) {
+        return new VariableInfo[] {
+            new VariableInfo(data.getAttributeString("id"), StopWatch.class.getName(), true, VariableInfo.AT_END)
+        };
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StopTag.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StopTag.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StopTag.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/StopTag.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,69 @@
+/*
+ * 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.web.jsp;
+
+import org.apache.sirona.stopwatches.StopWatch;
+
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.tagext.TagSupport;
+
+import static org.apache.sirona.web.jsp.TagUtils.getScope;
+
+/**
+ * A JSP tag to counter JSP rendering performances
+ *
+ * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
+ */
+public class StopTag extends TagSupport {
+    private String id;
+    private String scope;
+
+    /**
+     * @param id the id to set
+     */
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @see javax.servlet.jsp.tagext.TagSupport#doStartTag()
+     */
+    @Override
+    public int doStartTag() throws JspException {
+        StopWatch stopWatch;
+        if (scope != null) {
+            stopWatch = (StopWatch) pageContext.getAttribute(id, getScope(scope));
+        } else {
+            stopWatch = (StopWatch) pageContext.getAttribute(id);
+        }
+        if (stopWatch == null) {
+            throw new JspException("No StopWatch under ID " + id + " and scope " + scope);
+        }
+        stopWatch.stop();
+        return EVAL_PAGE;
+    }
+
+    /**
+     * @param scope the scope to set
+     */
+    public void setScope(final String scope) {
+        this.scope = scope;
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/TagUtils.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/TagUtils.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/TagUtils.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/jsp/TagUtils.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,43 @@
+/*
+ * 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.web.jsp;
+
+import javax.servlet.jsp.PageContext;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class TagUtils {
+    /**
+     * Maps JSP scope names to PageContext constants
+     */
+    private static final Map<String, Integer> scopes = new HashMap<String, Integer>();
+    static {
+        scopes.put("page", PageContext.PAGE_SCOPE);
+        scopes.put("request", PageContext.REQUEST_SCOPE);
+        scopes.put("session", PageContext.SESSION_SCOPE);
+        scopes.put("application", PageContext.APPLICATION_SCOPE);
+    }
+
+    public static int getScope(final String scopeName) {
+        return scopes.get(scopeName.toLowerCase());
+    }
+
+    private TagUtils() {
+        // no-op
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/lifecycle/SironaLifecycle.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/lifecycle/SironaLifecycle.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/lifecycle/SironaLifecycle.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/lifecycle/SironaLifecycle.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,35 @@
+/*
+ * 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.web.lifecycle;
+
+import org.apache.sirona.configuration.Configuration;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+// needs to be activate when commons-monitoring-core is in a webapp
+public class SironaLifecycle implements ServletContextListener {
+    @Override
+    public void contextInitialized(final ServletContextEvent sce) {
+        // no-op
+    }
+
+    @Override
+    public void contextDestroyed(final ServletContextEvent sce) {
+        Configuration.shutdown();
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/registration/WebMonitoringInitializer.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/registration/WebMonitoringInitializer.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/registration/WebMonitoringInitializer.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/registration/WebMonitoringInitializer.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,86 @@
+/*
+ * 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.web.registration;
+
+import org.apache.sirona.configuration.Configuration;
+import org.apache.sirona.repositories.Repository;
+import org.apache.sirona.util.Environment;
+import org.apache.sirona.web.discovery.GaugeDiscoveryListener;
+import org.apache.sirona.web.lifecycle.SironaLifecycle;
+import org.apache.sirona.web.servlet.MonitoringFilter;
+import org.apache.sirona.web.session.MonitoringSessionListener;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.FilterRegistration;
+import javax.servlet.ServletContainerInitializer;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import java.util.EnumSet;
+import java.util.Set;
+
+public class WebMonitoringInitializer implements ServletContainerInitializer {
+    private static final String ACTIVATED = Configuration.CONFIG_PROPERTY_PREFIX + "web.activated";
+    private static final String FALSE = Boolean.FALSE.toString();
+
+    @Override
+    public void onStartup(final Set<Class<?>> classes, final ServletContext ctx) throws ServletException {
+        if (Environment.isCollector()) {
+            return;
+        }
+
+        final String activated = ctx.getInitParameter(ACTIVATED);
+        if (FALSE.equalsIgnoreCase(Configuration.getProperty(ACTIVATED, activated))) {
+            return;
+        }
+
+        final String monStatus = Boolean.toString(!FALSE.equalsIgnoreCase(ctx.getInitParameter(MonitoringFilter.MONITOR_STATUS)));
+        ctx.setAttribute(MonitoringFilter.MONITOR_STATUS, monStatus);
+
+        ctx.addListener(MonitoringSessionListener.class);
+        ctx.addListener(GaugeDiscoveryListener.class);
+        if (ctx.getClassLoader().equals(Repository.class.getClassLoader())) {
+            ctx.addListener(SironaLifecycle.class);
+        }
+
+        String ignoredUrls = ctx.getInitParameter(MonitoringFilter.IGNORED_URLS);
+        String monitoredUrls = ctx.getInitParameter(Configuration.CONFIG_PROPERTY_PREFIX + "web.monitored-urls");
+        if (!"false".equalsIgnoreCase(monitoredUrls)) {
+            if (monitoredUrls == null) {
+                monitoredUrls = "/*";
+            }
+
+            if (ignoredUrls == null) {
+                ignoredUrls = Configuration.getProperty(MonitoringFilter.IGNORED_URLS, "/monitoring");
+            }
+
+            if (monitoredUrls.contains(",")) {
+                final String[] split = monitoredUrls.split(",");
+                for (int i = 0; i < split.length; i++) {
+                    final FilterRegistration.Dynamic filter = ctx.addFilter("monitoring-filter-" + i, MonitoringFilter.class);
+                    filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, split[i]);
+                    filter.setInitParameter(MonitoringFilter.MONITOR_STATUS, monStatus);
+                    filter.setInitParameter(MonitoringFilter.IGNORED_URLS, ignoredUrls);
+                }
+            } else {
+                final FilterRegistration.Dynamic filter = ctx.addFilter("monitoring-filter", MonitoringFilter.class);
+                filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, monitoredUrls);
+                filter.setInitParameter(MonitoringFilter.MONITOR_STATUS, monStatus);
+                filter.setInitParameter(MonitoringFilter.IGNORED_URLS, ignoredUrls);
+            }
+        }
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/servlet/MonitoringFilter.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/servlet/MonitoringFilter.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/servlet/MonitoringFilter.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/servlet/MonitoringFilter.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,143 @@
+/*
+ * 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.web.servlet;
+
+import org.apache.sirona.MonitoringException;
+import org.apache.sirona.Role;
+import org.apache.sirona.aop.AbstractPerformanceInterceptor;
+import org.apache.sirona.configuration.Configuration;
+import org.apache.sirona.web.discovery.GaugeDiscoveryListener;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Map;
+
+public class MonitoringFilter extends AbstractPerformanceInterceptor<MonitoringFilter.Invocation> implements Filter {
+    public static final String MONITOR_STATUS = Configuration.CONFIG_PROPERTY_PREFIX + "web.monitored-status";
+    public static final String IGNORED_URLS = Configuration.CONFIG_PROPERTY_PREFIX + "web.ignored-urls";
+
+    private String[] ignored = new String[0];
+    private Map<Integer, StatusGauge> statusGauges = null;
+
+    @Override
+    public void init(final FilterConfig filterConfig) throws ServletException {
+        final String ignoredUrls = filterConfig.getInitParameter(IGNORED_URLS);
+        if (ignoredUrls != null) {
+            ignored = ignoredUrls.split(",");
+        }
+
+        final String monStatus = filterConfig.getInitParameter(MONITOR_STATUS);
+        if ((monStatus == null || "true".equalsIgnoreCase(monStatus))
+                && filterConfig.getServletContext().getAttribute(GaugeDiscoveryListener.STATUS_GAUGES_ATTRIBUTE) == null) {
+            throw new MonitoringException("To monitor status activate " + GaugeDiscoveryListener.class.getName());
+        }
+
+        statusGauges = (Map<Integer, StatusGauge>) filterConfig.getServletContext().getAttribute(GaugeDiscoveryListener.STATUS_GAUGES_ATTRIBUTE);
+    }
+
+    @Override
+    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
+        if (HttpServletRequest.class.isInstance(request)) {
+            final HttpServletRequest httpRequest = HttpServletRequest.class.cast(request);
+
+            final String uri = getRequestedUri(httpRequest);
+            for (final String ignorable : ignored) {
+                if (uri.startsWith(ignorable)) {
+                    chain.doFilter(request, response);
+                    return;
+                }
+            }
+
+            final HttpServletResponse httpResponse = HttpServletResponse.class.cast(response);
+            try {
+                doInvoke(new Invocation(httpRequest, httpResponse, chain));
+            } catch (final Throwable throwable) {
+                if (IOException.class.isInstance(throwable)) {
+                    throw IOException.class.cast(throwable);
+                }
+                if (ServletException.class.isInstance(throwable)) {
+                    throw ServletException.class.cast(throwable);
+                }
+                throw new IOException(throwable);
+            } finally {
+                if (statusGauges != null) {
+                    final int status = httpResponse.getStatus();
+                    final StatusGauge statusGauge = statusGauges.get(status);
+                    if (statusGauge != null) {
+                        statusGauge.incr();
+                    }
+                }
+            }
+        } else {
+            // Not an HTTP request...
+            chain.doFilter(request, response);
+        }
+    }
+
+    @Override
+    protected Object proceed(final Invocation invocation) throws Throwable {
+        invocation.proceed();
+        return null;
+    }
+
+    @Override
+    protected String getCounterName(final Invocation invocation) {
+        return invocation.request.getRequestURI();
+    }
+
+    @Override
+    protected Role getRole() {
+        return Role.WEB;
+    }
+
+    @Override
+    public void destroy() {
+        // no-op
+    }
+
+    protected static String getRequestedUri(final HttpServletRequest request) {
+        final String uri = request.getRequestURI();
+        final String context = request.getContextPath();
+        if (uri.length() <= context.length()) {
+            return uri;
+        }
+        return uri.substring(context.length());
+    }
+
+    protected static class Invocation {
+        protected final HttpServletRequest request;
+        protected final HttpServletResponse response;
+        protected final FilterChain chain;
+
+        public Invocation(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) {
+            this.request = request;
+            this.response = response;
+            this.chain = chain;
+        }
+
+        public void proceed() throws IOException, ServletException {
+            chain.doFilter(request, response);
+        }
+    }
+}
\ No newline at end of file

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/servlet/StatusGauge.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/servlet/StatusGauge.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/servlet/StatusGauge.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/servlet/StatusGauge.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,58 @@
+/*
+ * 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.web.servlet;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.configuration.Configuration;
+import org.apache.sirona.gauges.Gauge;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public class StatusGauge implements Gauge {
+    private static final int PERIOD = Configuration.getInteger(Configuration.CONFIG_PROPERTY_PREFIX + "web.gauge.status.period", 4000);
+
+    private final Role role;
+    private final AtomicLong count = new AtomicLong(0);
+
+    public StatusGauge(final Role role) {
+        this.role = role;
+    }
+
+    @Override
+    public Role role() {
+        return role;
+    }
+
+    @Override
+    public double value() {
+        return count.getAndSet(0);
+    }
+
+    @Override
+    public long period() {
+        return PERIOD;
+    }
+
+    public void incr() {
+        count.incrementAndGet();
+    }
+
+    @Override
+    public String toString() {
+        return "StatusGauge{role=" + role + '}';
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/session/MonitoringSessionListener.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/session/MonitoringSessionListener.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/session/MonitoringSessionListener.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/session/MonitoringSessionListener.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,73 @@
+/*
+ * 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.web.session;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.counters.Unit;
+import org.apache.sirona.repositories.Repository;
+import org.apache.sirona.stopwatches.StopWatch;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class MonitoringSessionListener implements HttpSessionListener, ServletContextListener {
+    private final Map<String, StopWatch> watches = new ConcurrentHashMap<String, StopWatch>();
+
+    private final AtomicLong sessionNumber = new AtomicLong(0);
+
+    private Counter counter;
+    private SessionGauge gauge;
+
+    @Override
+    public void sessionCreated(final HttpSessionEvent httpSessionEvent) {
+        final StopWatch watch = Repository.INSTANCE.start(counter);
+        watches.put(httpSessionEvent.getSession().getId(), watch);
+        sessionNumber.incrementAndGet();
+    }
+
+    @Override
+    public void sessionDestroyed(final HttpSessionEvent httpSessionEvent) {
+        final StopWatch watch = watches.remove(httpSessionEvent.getSession().getId());
+        if (watch != null) {
+            watch.stop();
+        }
+        sessionNumber.decrementAndGet();
+    }
+
+    @Override
+    public void contextInitialized(final ServletContextEvent sce) {
+        String contextPath = sce.getServletContext().getContextPath();
+        if (contextPath == null || contextPath.isEmpty()) {
+            contextPath = "/";
+        }
+        counter = Repository.INSTANCE.getCounter(new Counter.Key(new Role("session-durations", Unit.Time.NANOSECOND), "session-durations-" + contextPath));
+
+        gauge = new SessionGauge(contextPath, sessionNumber);
+        Repository.INSTANCE.addGauge(gauge);
+    }
+
+    @Override
+    public void contextDestroyed(final ServletContextEvent sce) {
+        Repository.INSTANCE.stopGauge(gauge);
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/session/SessionGauge.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/session/SessionGauge.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/session/SessionGauge.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/java/org/apache/sirona/web/session/SessionGauge.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,62 @@
+/*
+ * 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.web.session;
+
+import org.apache.sirona.Role;
+import org.apache.sirona.configuration.Configuration;
+import org.apache.sirona.counters.Unit;
+import org.apache.sirona.gauges.Gauge;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class SessionGauge implements Gauge {
+    private static final WeakHashMap<Role, SessionGauge> GAUGES = new WeakHashMap<Role, SessionGauge>();
+
+    public static Map<Role, SessionGauge> gauges() {
+        return new HashMap<Role, SessionGauge>(GAUGES);
+    }
+
+    private final Role role;
+    private final AtomicLong counter;
+
+    public SessionGauge(final String ctx, final AtomicLong counter) {
+        this.role = new Role("sessions-" + ctx, Unit.UNARY);
+        this.counter = counter;
+
+        synchronized (GAUGES) {
+            GAUGES.put(role, this);
+        }
+    }
+
+    @Override
+    public Role role() {
+        return role;
+    }
+
+    @Override
+    public double value() {
+        return counter.get();
+    }
+
+    @Override
+    public long period() {
+        return Configuration.getInteger(Configuration.CONFIG_PROPERTY_PREFIX + "web.gauge.sessions.period", 4000);
+    }
+}

Added: incubator/sirona/trunk/agent/performance/web/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer (added)
+++ incubator/sirona/trunk/agent/performance/web/src/main/resources/META-INF/services/javax.servlet.ServletContainerInitializer Tue Nov  5 17:25:15 2013
@@ -0,0 +1 @@
+org.apache.sirona.web.registration.WebMonitoringInitializer

Added: incubator/sirona/trunk/agent/performance/web/src/test/java/org/apache/sirona/test/web/HittableServlet.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/performance/web/src/test/java/org/apache/sirona/test/web/HittableServlet.java?rev=1539076&view=auto
==============================================================================
--- incubator/sirona/trunk/agent/performance/web/src/test/java/org/apache/sirona/test/web/HittableServlet.java (added)
+++ incubator/sirona/trunk/agent/performance/web/src/test/java/org/apache/sirona/test/web/HittableServlet.java Tue Nov  5 17:25:15 2013
@@ -0,0 +1,42 @@
+/*
+ * 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.test.web;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+
+@WebServlet(urlPatterns = "/hit")
+public class HittableServlet extends HttpServlet {
+    @Override
+    protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
+        final String statusStr = req.getParameter("status");
+        final int status;
+        if (statusStr != null) {
+            status = Integer.parseInt(statusStr);
+        } else {
+            status = HttpURLConnection.HTTP_OK;
+        }
+
+        resp.setStatus(status);
+        resp.getWriter().write("answered");
+    }
+}