Index: cocoon-servlet/src/main/java/org/apache/cocoon/servlet/XMLSitemapServlet.java
===================================================================
--- cocoon-servlet/src/main/java/org/apache/cocoon/servlet/XMLSitemapServlet.java	(revision 800882)
+++ cocoon-servlet/src/main/java/org/apache/cocoon/servlet/XMLSitemapServlet.java	(working copy)
@@ -34,6 +34,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.cocoon.configuration.Settings;
+import org.apache.cocoon.monitoring.statistics.RequestCounter;
 import org.apache.cocoon.servlet.node.LastModifiedCollector;
 import org.apache.cocoon.servlet.node.MimeTypeCollector;
 import org.apache.cocoon.servlet.node.StatusCodeCollector;
@@ -62,6 +63,7 @@
     private ServletConfig servletConfig;
     private SitemapNode sitemapNode;
     private String version = "";
+    private RequestCounter requestCounter;
 
     @Override
     public void init(ServletConfig config) throws ServletException {
@@ -150,6 +152,13 @@
 
             // Status code handling
             int statusCode = StatusCodeCollector.getStatusCode();
+            if (this.requestCounter != null) { // update request statistics
+                if (statusCode >= 200 && statusCode < 300) {
+                    this.requestCounter.increnetGoodRequestCounter();
+                } else if (statusCode >= 400 && statusCode < 600) {
+                    this.requestCounter.incrementBadRequestCounter();
+                }
+            }
             response.setStatus(statusCode);
 
             // write the sitemap result to the output stream
@@ -245,6 +254,7 @@
             } catch (Exception e) {
                 throw this.wrapException(e, "An exception occurred while building the sitemap.");
             }
+            this.requestCounter = (RequestCounter) this.beanFactory.getBean(RequestCounter.class.getName());
             this.initialized = true;
         }
     }
Index: cocoon-servlet/pom.xml
===================================================================
--- cocoon-servlet/pom.xml	(revision 800882)
+++ cocoon-servlet/pom.xml	(working copy)
@@ -50,6 +50,10 @@
       <groupId>org.apache.cocoon.sax</groupId>
       <artifactId>cocoon-sax</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.cocoon.monitoring</groupId>
+      <artifactId>cocoon-monitoring</artifactId>
+    </dependency>
 
     <!-- Cocoon subprojects -->
     <dependency>
Index: cocoon-monitoring/src/main/java/org/apache/cocoon/monitoring/statistics/StatisticsCollector.java
===================================================================
--- cocoon-monitoring/src/main/java/org/apache/cocoon/monitoring/statistics/StatisticsCollector.java	(revision 0)
+++ cocoon-monitoring/src/main/java/org/apache/cocoon/monitoring/statistics/StatisticsCollector.java	(revision 0)
@@ -0,0 +1,99 @@
+/*
+ * 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.cocoon.monitoring.statistics;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class StatisticsCollector {
+
+    /**
+     * Default refresh time: 10s;
+     */
+    public static final long DEFAULT_REFRESH_DELAY = 1000 * 10;
+
+    /**
+     * Default value of maxKeepTime: 24h.
+     */
+    public static final long DEFAULT_MAX_KEEP_TIME = 1000 * 60 * 60 * 24;
+
+    private final List<Long> requestCoutner;
+    private final long maxKeepTime;
+    private double allHitCount = 0;
+
+    public StatisticsCollector() {
+        this(DEFAULT_MAX_KEEP_TIME, DEFAULT_REFRESH_DELAY);
+    }
+
+    public StatisticsCollector(long maxKeepTime, long refreshDelay) {
+        this.maxKeepTime = maxKeepTime;
+        this.requestCoutner = Collections.synchronizedList(new ArrayList<Long>());
+
+        initCleaningThread(refreshDelay);
+    }
+
+    public double getAllHitCount() {
+        return this.allHitCount;
+    }
+
+    public long getRequestCount(long time) {
+        if (time == this.maxKeepTime) {
+            return this.requestCoutner.size();
+        }
+
+        long counter = 0;
+        long currentTimestamp = new Date().getTime() - time;
+
+        for (Long timestamp : this.requestCoutner) {
+            if (timestamp <= currentTimestamp) {
+                counter++;
+            }
+        }
+
+        return counter;
+    }
+
+    public void incerementCounter() {
+        this.allHitCount++;
+        this.requestCoutner.add(new Date().getTime());
+    }
+
+    private void initCleaningThread(long refreshDelay) {
+        Timer cleaningTimer = new Timer("RequestCounterCleaningTask", true);
+        cleaningTimer.scheduleAtFixedRate(new TimerTask() {
+
+            @Override
+            public void run() {
+                List<Long> toRemove = new ArrayList<Long>();
+                for (Long timestamp : StatisticsCollector.this.requestCoutner) {
+                    if (timestamp > StatisticsCollector.this.maxKeepTime) {
+                        toRemove.add(timestamp);
+                    }
+                }
+
+                StatisticsCollector.this.requestCoutner.removeAll(toRemove);
+            }
+        }, refreshDelay, refreshDelay);
+    }
+
+}
Index: cocoon-monitoring/src/main/java/org/apache/cocoon/monitoring/statistics/RequestCounter.java
===================================================================
--- cocoon-monitoring/src/main/java/org/apache/cocoon/monitoring/statistics/RequestCounter.java	(revision 0)
+++ cocoon-monitoring/src/main/java/org/apache/cocoon/monitoring/statistics/RequestCounter.java	(revision 0)
@@ -0,0 +1,101 @@
+/*
+ * 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.cocoon.monitoring.statistics;
+
+import org.springframework.jmx.export.annotation.ManagedAttribute;
+import org.springframework.jmx.export.annotation.ManagedOperationParameter;
+import org.springframework.jmx.export.annotation.ManagedOperationParameters;
+import org.springframework.jmx.export.annotation.ManagedResource;
+
+
+
+@ManagedResource(objectName = "org.apache.cocoon.monitoring:group=Monitoring,name=RequestCounter")
+public class RequestCounter {
+
+        private final StatisticsCollector badRequestCounter;
+        private final StatisticsCollector goodRequestCounter;
+
+        public RequestCounter() {
+            this.badRequestCounter = new StatisticsCollector();
+            this.goodRequestCounter = new StatisticsCollector();
+        }
+
+        public void incrementBadRequestCounter() {
+            this.badRequestCounter.incerementCounter();
+        }
+
+        public void increnetGoodRequestCounter() {
+            this.goodRequestCounter.incerementCounter();
+        }
+
+        @ManagedAttribute(description = "Returns all request count (good and bad) since system start.")
+        public final double getAllRequestCount() {
+            return this.goodRequestCounter.getAllHitCount() + this.badRequestCounter.getAllHitCount();
+        }
+
+        @ManagedAttribute(description = "Returns bad request count (eg. 404, 500, 501) since system start.")
+        public final double getAllBadRequestCount() {
+            return this.badRequestCounter.getAllHitCount();
+        }
+
+        @ManagedAttribute(description = "Returns good request count since system start.")
+        public final double getAllGoodRequestCount() {
+            return this.goodRequestCounter.getAllHitCount();
+        }
+
+        @ManagedAttribute(description = "Returns bad request count (status codes: 4xx and 5xx) in last 5 minutes.")
+        public final long getBadRequestCountInLast5Minutes() {
+            return this.badRequestCounter.getRequestCount(1000 * 60 * 5);
+        }
+
+        @ManagedAttribute(description = "Returns bad request count (status codes: 4xx and 5xx) in last 60 minutes.")
+        public final long getBadRequestCountInLastHour() {
+            return this.badRequestCounter.getRequestCount(1000 * 60 * 60);
+        }
+
+        @ManagedAttribute(description = "Returns bad request count (status codes: 4xx and 5xx) in last 24 hours.")
+        public final long getBadRequestCounInLast24Hours() {
+            return this.badRequestCounter.getRequestCount(1000 * 60 * 60 * 24);
+        }
+
+        @ManagedAttribute(description = "Returns bad request count (status codes: 4xx and 5xx) in specified time.")
+        @ManagedOperationParameters(@ManagedOperationParameter(name = "time", description = "Time in past in milliseconds"))
+        public final long getBadRequestCountInSpecyfiedTime(long time) {
+            return this.badRequestCounter.getRequestCount(time);
+        }
+
+        @ManagedAttribute(description = "Returns good request count (status codes 2xx) in last 5 minutes.")
+        public final long getGoodRequestCountInLast5Minutes() {
+            return this.goodRequestCounter.getRequestCount(1000 * 60 * 5);
+        }
+
+        @ManagedAttribute(description = "Returns good request count (status codes 2xx) in last 60 minutes.")
+        public final long getGoodRequestCountInLastHour() {
+            return this.goodRequestCounter.getRequestCount(1000 * 60 * 60);
+        }
+
+        @ManagedAttribute(description = "Returns good request count (status codes 2xx) in last 24 hours.")
+        public final long getGoodRequestCounInLast24Hours() {
+            return this.goodRequestCounter.getRequestCount(1000 * 60 * 60 * 24);
+        }
+
+        @ManagedAttribute(description = "Returns good request count (status codes 2xx) in specified time.")
+        @ManagedOperationParameters(@ManagedOperationParameter(name = "time", description = "Time in past in milliseconds"))
+        public final long getGoodRequestCountInSpecyfiedTime(long time) {
+            return this.goodRequestCounter.getRequestCount(time);
+    }
+}
Index: cocoon-monitoring/src/main/java/org/apache/cocoon/monitoring/statistics/RequestStatisticsCollector.java
===================================================================
--- cocoon-monitoring/src/main/java/org/apache/cocoon/monitoring/statistics/RequestStatisticsCollector.java	(revision 0)
+++ cocoon-monitoring/src/main/java/org/apache/cocoon/monitoring/statistics/RequestStatisticsCollector.java	(revision 0)
@@ -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.cocoon.monitoring.statistics;
+
+public interface RequestStatisticsCollector {
+
+    void incrementBadRequestCounter();
+
+    void increnetGoodRequestCounter();
+
+}
Index: cocoon-monitoring/src/main/resources/META-INF/cocoon/spring/cocoon-monitoring.xml
===================================================================
--- cocoon-monitoring/src/main/resources/META-INF/cocoon/spring/cocoon-monitoring.xml	(revision 800882)
+++ cocoon-monitoring/src/main/resources/META-INF/cocoon/spring/cocoon-monitoring.xml	(working copy)
@@ -53,4 +57,26 @@
     <constructor-arg ref="exporter" index="1"/>
   </bean>
 
+  <bean id="org.apache.cocoon.monitoring.statistics.RequestCounter" class="org.apache.cocoon.monitoring.statistics.RequestCounter" scope="singleton" />
+  
 </beans>

