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/07 11:50:38 UTC

svn commit: r1539590 - in /incubator/sirona/trunk: agent/pull/ agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/repository/ agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/servlet/ agent/store/cube/src/main/java/org/apache/siro...

Author: rmannibucau
Date: Thu Nov  7 10:50:38 2013
New Revision: 1539590

URL: http://svn.apache.org/r1539590
Log:
adding registration + basic test for pull collection mode

Added:
    incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/AgentNode.java
    incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/
    incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SSLSocketFactoryProvider.java
    incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SecurityProvider.java
    incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/RegistrationTest.java
    incubator/sirona/trunk/src/site/markdown/deployments.md
Modified:
    incubator/sirona/trunk/agent/pull/pom.xml
    incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/repository/PullRepository.java
    incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/servlet/PullServlet.java
    incubator/sirona/trunk/agent/store/cube/src/main/java/org/apache/sirona/cube/Cube.java
    incubator/sirona/trunk/core/src/main/java/org/apache/sirona/repositories/DefaultRepository.java
    incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/Collector.java
    incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java
    incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/gauge/DelegatedCollectorGaugeDataStore.java
    incubator/sirona/trunk/server/collector/src/main/resources/collector-sirona.properties
    incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/CollectorServer.java
    incubator/sirona/trunk/src/site/markdown/index.md

Modified: incubator/sirona/trunk/agent/pull/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/pull/pom.xml?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/pull/pom.xml (original)
+++ incubator/sirona/trunk/agent/pull/pom.xml Thu Nov  7 10:50:38 2013
@@ -55,5 +55,9 @@
       <classifier>jdk15</classifier>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-codec-http</artifactId>
+    </dependency>
   </dependencies>
 </project>

Modified: incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/repository/PullRepository.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/repository/PullRepository.java?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/repository/PullRepository.java (original)
+++ incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/repository/PullRepository.java Thu Nov  7 10:50:38 2013
@@ -20,6 +20,7 @@ import org.apache.sirona.agent.webapp.pu
 import org.apache.sirona.configuration.Configuration;
 import org.apache.sirona.cube.Cube;
 import org.apache.sirona.cube.CubeBuilder;
+import org.apache.sirona.cube.MapBuilder;
 import org.apache.sirona.gauges.Gauge;
 import org.apache.sirona.gauges.GaugeDataStoreAdapter;
 import org.apache.sirona.gauges.GaugeManager;
@@ -34,8 +35,7 @@ import java.util.Collection;
 import java.util.Collections;
 
 public class PullRepository extends DefaultRepository {
-    private static final char START_ARRAY = '[';
-    private static final char END_ARRAY = ']';
+    private static final String REGISTRATION_TYPE = "registration";
 
     private final Cube cube;
 
@@ -75,9 +75,14 @@ public class PullRepository extends Defa
 
         // remove last ','
         if (answer.length() == 0) {
-            return Character.toString(START_ARRAY) + END_ARRAY;
+            return null;
+        }
+        return cube.globalPayload(answer);
+    }
+
+    public void register(final String registrationUrl) {
+        if (registrationUrl != null) {
+            cube.post(cube.buildEvent(cube.newEventStream(), REGISTRATION_TYPE, 0, new MapBuilder().add("url", registrationUrl).map()));
         }
-        answer.setLength(answer.length() - 1);
-        return START_ARRAY + answer.toString() + END_ARRAY;
     }
 }

Modified: incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/servlet/PullServlet.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/servlet/PullServlet.java?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/servlet/PullServlet.java (original)
+++ incubator/sirona/trunk/agent/pull/src/main/java/org/apache/sirona/agent/webapp/pull/servlet/PullServlet.java Thu Nov  7 10:50:38 2013
@@ -19,8 +19,10 @@
 package org.apache.sirona.agent.webapp.pull.servlet;
 
 import org.apache.sirona.agent.webapp.pull.repository.PullRepository;
+import org.apache.sirona.configuration.Configuration;
 import org.apache.sirona.repositories.Repository;
 
+import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
@@ -33,8 +35,14 @@ public class PullServlet extends HttpSer
     private PullRepository repository;
 
     @Override
-    public void init() throws ServletException {
+    public void init(final ServletConfig config) throws ServletException {
+        super.init(config);
         repository = PullRepository.class.cast(Repository.INSTANCE);
+
+        final String registration = config.getInitParameter(Configuration.CONFIG_PROPERTY_PREFIX + "pull.url");
+        if (registration != null) { // needs to have configured org.apache.sirona.cube.CubeBuilder in sirona.properties
+            repository.register(registration);
+        } // else collector should be aware or it with another way -> config in the collector
     }
 
     @Override

Modified: incubator/sirona/trunk/agent/store/cube/src/main/java/org/apache/sirona/cube/Cube.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/agent/store/cube/src/main/java/org/apache/sirona/cube/Cube.java?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/agent/store/cube/src/main/java/org/apache/sirona/cube/Cube.java (original)
+++ incubator/sirona/trunk/agent/store/cube/src/main/java/org/apache/sirona/cube/Cube.java Thu Nov  7 10:50:38 2013
@@ -67,8 +67,8 @@ public class Cube {
 
     private static final String POST = "POST";
     private static final String CONTENT_TYPE = "Content-Type";
-    private static final String CONTENT_LENGTH = "Content-Length";
     private static final String APPLICATION_JSON = "application/json";
+    private static final String CONTENT_LENGTH = "Content-Length";
 
     private static final String JS_ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
     private static final String UTC = "UTC";
@@ -97,9 +97,16 @@ public class Cube {
         return new StringBuilder();
     }
 
+    public String globalPayload(final StringBuilder payload) {
+        if (payload.length() > 0) {
+            return finalPayload(payload.substring(0, payload.length() - 1));
+        }
+        return finalPayload(payload.toString());
+    }
+
     public void post(final StringBuilder payload) {
         if (payload.length() > 0) {
-            doPost(finalPayload(payload.substring(0, payload.length() - 1)));
+            doPost(globalPayload(payload));
         }
     }
 

Modified: incubator/sirona/trunk/core/src/main/java/org/apache/sirona/repositories/DefaultRepository.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/core/src/main/java/org/apache/sirona/repositories/DefaultRepository.java?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/core/src/main/java/org/apache/sirona/repositories/DefaultRepository.java (original)
+++ incubator/sirona/trunk/core/src/main/java/org/apache/sirona/repositories/DefaultRepository.java Thu Nov  7 10:50:38 2013
@@ -174,7 +174,9 @@ public class DefaultRepository implement
     @Override
     public void reset() {
         clearCounters();
-        gaugeManager.stop();
+        if (gaugeManager != null) {
+            gaugeManager.stop();
+        }
         nodeStatusDataStore.reset();
     }
 

Added: incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/AgentNode.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/AgentNode.java?rev=1539590&view=auto
==============================================================================
--- incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/AgentNode.java (added)
+++ incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/AgentNode.java Thu Nov  7 10:50:38 2013
@@ -0,0 +1,66 @@
+/*
+ * 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.collector.server;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class AgentNode {
+    public static final int DEAD_COUNT = 5;
+    private final URL url;
+    private final AtomicLong missed = new AtomicLong(0);
+
+    public AgentNode(final String url) throws MalformedURLException {
+        this.url = new URL(url);
+    }
+
+    public URL getUrl() {
+        return url;
+    }
+
+    public void ok() {
+        missed.set(0);
+    }
+
+    public void ko() {
+        missed.incrementAndGet();
+    }
+
+    public boolean isDead() {
+        return missed.get() > DEAD_COUNT;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        final AgentNode agentNode = AgentNode.class.cast(o);
+        return !(url != null ? !url.equals(agentNode.url) : agentNode.url != null);
+
+    }
+
+    @Override
+    public int hashCode() {
+        return url != null ? url.hashCode() : 0;
+    }
+}

Modified: incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/Collector.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/Collector.java?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/Collector.java (original)
+++ incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/Collector.java Thu Nov  7 10:50:38 2013
@@ -19,7 +19,10 @@ package org.apache.sirona.collector.serv
 import com.fasterxml.jackson.core.JsonParser;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.sirona.MonitoringException;
 import org.apache.sirona.Role;
+import org.apache.sirona.collector.server.api.SSLSocketFactoryProvider;
+import org.apache.sirona.collector.server.api.SecurityProvider;
 import org.apache.sirona.configuration.Configuration;
 import org.apache.sirona.counters.Counter;
 import org.apache.sirona.counters.Unit;
@@ -28,22 +31,38 @@ import org.apache.sirona.repositories.Re
 import org.apache.sirona.status.NodeStatus;
 import org.apache.sirona.status.Status;
 import org.apache.sirona.status.ValidationResult;
+import org.apache.sirona.store.BatchFuture;
 import org.apache.sirona.store.counter.CollectorCounterStore;
 import org.apache.sirona.store.gauge.CollectorGaugeDataStore;
 import org.apache.sirona.store.status.CollectorNodeStatusDataStore;
 import org.apache.sirona.store.status.NodeStatusDataStore;
+import org.apache.sirona.util.DaemonThreadFactory;
 
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSocketFactory;
+import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 // should work with cube clients, see cube module for details
@@ -55,6 +74,9 @@ public class Collector extends HttpServl
     private static final String GAUGE = "gauge";
     private static final String COUNTER = "counter";
     private static final String VALIDATION = "validation";
+    private static final String REGISTRATION = "registration";
+
+    private static final String GET = "GET";
 
     private final Map<String, Role> roles = new ConcurrentHashMap<String, Role>();
 
@@ -63,8 +85,16 @@ public class Collector extends HttpServl
     private CollectorNodeStatusDataStore statusDataStore;
     private ObjectMapper mapper;
 
+    private final Collection<AgentNode> agents = new CopyOnWriteArraySet<AgentNode>();
+    private volatile BatchFuture collectionFuture = null;
+    private long collectionPeriod;
+    private SecurityProvider securityProvider;
+    private SSLSocketFactoryProvider sslSocketFactoryProvider;
+
     @Override
-    public void init() {
+    public void init(final ServletConfig sc) throws ServletException {
+        super.init(sc);
+
         // force init to ensure we have stores
         Configuration.findOrCreateInstance(Repository.class);
 
@@ -93,11 +123,74 @@ public class Collector extends HttpServl
         }
 
         this.mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true);
+
+        { // pulling
+            {
+                final String periodKey = Configuration.CONFIG_PROPERTY_PREFIX + "collector.collection.period";
+                final String collectionPeriodStr = sc.getInitParameter(periodKey);
+                if (collectionPeriodStr != null) {
+                    collectionPeriod = Integer.parseInt(collectionPeriodStr);
+                } else {
+                    collectionPeriod = Configuration.getInteger(periodKey, 60000);
+                }
+            }
+
+            {
+                final String agentUrlsKey = Configuration.CONFIG_PROPERTY_PREFIX + "collector.collection.agent-urls";
+                for (final String agents : new String[]{
+                    Configuration.getProperty(agentUrlsKey, null),
+                    sc.getInitParameter(agentUrlsKey)
+                }) {
+                    if (agents != null) {
+                        for (final String url : agents.split(",")) {
+                            try {
+                                registerNode(url.trim());
+                            } catch (final MalformedURLException e) {
+                                throw new MonitoringException(e);
+                            }
+                        }
+                    }
+                }
+            }
+
+            try {
+                securityProvider = Configuration.findOrCreateInstance(SecurityProvider.class);
+            } catch (final Exception e) {
+                securityProvider = null;
+            }
+
+            try {
+                sslSocketFactoryProvider = Configuration.findOrCreateInstance(SSLSocketFactoryProvider.class);
+            } catch (final Exception e) {
+                sslSocketFactoryProvider = null;
+            }
+        }
+    }
+
+    @Override
+    public void destroy() {
+        if (collectionFuture != null) {
+            collectionFuture.done();
+        }
     }
 
     @Override
     protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
-        final Event[] events = mapper.readValue(req.getInputStream(), Event[].class);
+        final ServletInputStream inputStream = req.getInputStream();
+        try {
+            slurpEvents(inputStream);
+        } catch (final MonitoringException me) {
+            resp.setStatus(HttpURLConnection.HTTP_BAD_REQUEST);
+            resp.getWriter().write("{\"error\":\"" + me.getCause().getMessage().replace('\"', ' ') + "\"}");
+            return;
+        }
+
+        resp.setStatus(HttpURLConnection.HTTP_OK);
+        resp.getWriter().write(OK);
+    }
+
+    private void slurpEvents(final InputStream inputStream) throws IOException {
+        final Event[] events = mapper.readValue(inputStream, Event[].class);
         if (events != null && events.length > 0) {
             try {
                 final Collection<Event> validations = new LinkedList<Event>();
@@ -109,6 +202,8 @@ public class Collector extends HttpServl
                         updateCounter(event);
                     } else if (GAUGE.equals(type)) {
                         updateGauge(event);
+                    } else if (REGISTRATION.equals(type)) {
+                        registerNode(event);
                     } else {
                         LOGGER.info("Unexpected type '" + type + "', skipping");
                     }
@@ -127,27 +222,45 @@ public class Collector extends HttpServl
                     statusDataStore.store((String) events[0].getData().get("marker"), status);
                 }
             } catch (final Exception e) {
-                resp.setStatus(HttpURLConnection.HTTP_BAD_REQUEST);
-                resp.getWriter().write("{\"error\":\"" + e.getMessage().replace('\"', ' ') + "\"}");
-                return;
+                throw new MonitoringException(e);
             }
         }
+    }
 
-        resp.setStatus(HttpURLConnection.HTTP_OK);
-        resp.getWriter().write(OK);
+    private void registerNode(final Event event) throws MalformedURLException {
+        registerNode(String.class.cast(event.getData().get("url")));
+    }
+
+    private void registerNode(final String url) throws MalformedURLException {
+        if (url == null) {
+            return;
+        }
+
+        final AgentNode node = new AgentNode(url);
+        if (agents.add(node)) {
+            if (collectionFuture == null) {
+                synchronized (this) {
+                    if (collectionFuture == null) {
+                        final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(new DaemonThreadFactory("collector-pull-schedule"));
+                        final ScheduledFuture<?> future = ses.scheduleAtFixedRate(new CollectTask(), collectionPeriod, collectionPeriod, TimeUnit.MILLISECONDS);
+                        collectionFuture = new BatchFuture(ses, future);
+                    }
+                }
+            }
+        }
     }
 
     private void updateGauge(final Event event) {
-        final Map<String,Object> data = event.getData();
+        final Map<String, Object> data = event.getData();
 
         final long time = event.getTime().getTime();
-        final double value= Number.class.cast(data.get("value")).doubleValue();
+        final double value = Number.class.cast(data.get("value")).doubleValue();
 
         gaugeDataStore.addToGauge(role(data), time, value, String.class.cast(data.get("marker")));
     }
 
     private void updateCounter(final Event event) {
-        final Map<String,Object> data = event.getData();
+        final Map<String, Object> data = event.getData();
 
         counterDataStore.update(
             new Counter.Key(role(data), String.class.cast(data.get("name"))),
@@ -167,4 +280,63 @@ public class Collector extends HttpServl
         roles.put(name, created);
         return created;
     }
+
+    private class CollectTask implements Runnable {
+        @Override
+        public void run() {
+            final Iterator<AgentNode> nodes = agents.iterator();
+            while (nodes.hasNext()) {
+                final AgentNode agent = nodes.next();
+                try {
+                    final URL url = agent.getUrl();
+                    final HttpURLConnection connection = HttpURLConnection.class.cast(url.openConnection());
+
+                    if (sslSocketFactoryProvider != null) {
+                        final SSLSocketFactory sf = sslSocketFactoryProvider.sslSocketFactory(url.toExternalForm());
+                        if (sf != null && "https".equals(agent.getUrl().getProtocol())) {
+                            HttpsURLConnection.class.cast(connection).setSSLSocketFactory(sf);
+                        }
+                    }
+
+                    if (securityProvider != null) {
+                        final String auth = securityProvider.basicHeader(url.toExternalForm());
+                        if (auth != null) {
+                            connection.setRequestProperty("Authorization", auth);
+                        }
+                    }
+
+                    connection.setRequestMethod(GET);
+
+                    InputStream inputStream = null;
+                    try {
+                        inputStream = connection.getInputStream();
+                        slurpEvents(inputStream);
+                    } finally {
+                        connection.disconnect();
+                        if (inputStream != null) {
+                            try {
+                                inputStream.close();
+                            } catch (final IOException ioe) {
+                                // no-op
+                            }
+                        }
+                    }
+
+                    final int status = connection.getResponseCode();
+                    if (status / 100 == 2) {
+                        agent.ok();
+                    } else {
+                        agent.ko();
+                    }
+                } catch (final IOException e) {
+                    LOGGER.log(Level.SEVERE, e.getMessage(), e);
+                    agent.ko();
+                }
+
+                if (agent.isDead()) {
+                    nodes.remove();
+                }
+            }
+        }
+    }
 }

Added: incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SSLSocketFactoryProvider.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SSLSocketFactoryProvider.java?rev=1539590&view=auto
==============================================================================
--- incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SSLSocketFactoryProvider.java (added)
+++ incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SSLSocketFactoryProvider.java Thu Nov  7 10:50:38 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.collector.server.api;
+
+import javax.net.ssl.SSLSocketFactory;
+
+public interface SSLSocketFactoryProvider {
+    SSLSocketFactory sslSocketFactory(String url);
+}

Added: incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SecurityProvider.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SecurityProvider.java?rev=1539590&view=auto
==============================================================================
--- incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SecurityProvider.java (added)
+++ incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/api/SecurityProvider.java Thu Nov  7 10:50:38 2013
@@ -0,0 +1,21 @@
+/*
+ * 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.collector.server.api;
+
+public interface SecurityProvider {
+    String basicHeader(String url);
+}

Modified: incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java (original)
+++ incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/counter/InMemoryCollectorCounterStore.java Thu Nov  7 10:50:38 2013
@@ -16,9 +16,9 @@
  */
 package org.apache.sirona.collector.server.store.counter;
 
-import org.apache.sirona.store.counter.CollectorCounterStore;
-import org.apache.sirona.math.M2AwareStatisticalSummary;
 import org.apache.sirona.counters.Counter;
+import org.apache.sirona.math.M2AwareStatisticalSummary;
+import org.apache.sirona.store.counter.CollectorCounterStore;
 import org.apache.sirona.store.counter.InMemoryCounterDataStore;
 
 import java.util.Collection;

Modified: incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/gauge/DelegatedCollectorGaugeDataStore.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/gauge/DelegatedCollectorGaugeDataStore.java?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/gauge/DelegatedCollectorGaugeDataStore.java (original)
+++ incubator/sirona/trunk/server/collector/src/main/java/org/apache/sirona/collector/server/store/gauge/DelegatedCollectorGaugeDataStore.java Thu Nov  7 10:50:38 2013
@@ -142,4 +142,8 @@ public class DelegatedCollectorGaugeData
             store.gaugeStopped(gauge);
         }
     }
+
+    public void reset() {
+        dataStores.clear();
+    }
 }

Modified: incubator/sirona/trunk/server/collector/src/main/resources/collector-sirona.properties
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/main/resources/collector-sirona.properties?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/server/collector/src/main/resources/collector-sirona.properties (original)
+++ incubator/sirona/trunk/server/collector/src/main/resources/collector-sirona.properties Thu Nov  7 10:50:38 2013
@@ -17,3 +17,4 @@
 
 # collector data store to aggregate data
 org.apache.sirona.store.DataStoreFactory = org.apache.sirona.collector.server.store.CollectorDataStoreFactory
+org.apache.sirona.core.gauge.activated = false
\ No newline at end of file

Modified: incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/CollectorServer.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/CollectorServer.java?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/CollectorServer.java (original)
+++ incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/CollectorServer.java Thu Nov  7 10:50:38 2013
@@ -37,6 +37,9 @@ import io.netty.handler.codec.http.HttpR
 import io.netty.handler.codec.http.HttpVersion;
 import io.netty.handler.stream.ChunkedWriteHandler;
 
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
 import javax.servlet.ServletInputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -50,6 +53,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.net.ServerSocket;
 import java.nio.charset.Charset;
+import java.util.Enumeration;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -147,7 +151,31 @@ public class CollectorServer {
 
         private RequestHandler() {
             collector = new Collector();
-            collector.init();
+            try { // no need to call destroy since we don't start the timer
+                collector.init(new ServletConfig() {
+                    @Override
+                    public String getServletName() {
+                        return null;
+                    }
+
+                    @Override
+                    public ServletContext getServletContext() {
+                        return null;
+                    }
+
+                    @Override
+                    public String getInitParameter(String name) {
+                        return null;
+                    }
+
+                    @Override
+                    public Enumeration<String> getInitParameterNames() {
+                        return null;
+                    }
+                });
+            } catch (final ServletException e) {
+                // no-op
+            }
         }
 
         @Override

Added: incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/RegistrationTest.java
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/RegistrationTest.java?rev=1539590&view=auto
==============================================================================
--- incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/RegistrationTest.java (added)
+++ incubator/sirona/trunk/server/collector/src/test/java/org/apache/sirona/collector/server/RegistrationTest.java Thu Nov  7 10:50:38 2013
@@ -0,0 +1,196 @@
+/*
+ * 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.collector.server;
+
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.FullHttpRequest;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponseEncoder;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
+import io.netty.handler.stream.ChunkedWriteHandler;
+import org.apache.sirona.MonitoringException;
+import org.apache.sirona.Role;
+import org.apache.sirona.collector.server.store.gauge.DelegatedCollectorGaugeDataStore;
+import org.apache.sirona.configuration.Configuration;
+import org.apache.sirona.counters.Counter;
+import org.apache.sirona.repositories.Repository;
+import org.apache.sirona.store.gauge.CollectorGaugeDataStore;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class RegistrationTest {
+    private HttpServer agent;
+
+    @Before
+    public void start() {
+        agent = new HttpServer("localhost", 1234).start();
+        Repository.INSTANCE.reset();
+        DelegatedCollectorGaugeDataStore.class.cast(Configuration.getInstance(CollectorGaugeDataStore.class)).reset();
+    }
+
+    @After
+    public void shutdown() {
+        agent.stop();
+        Repository.INSTANCE.reset();
+    }
+
+    @Test
+    public void pull() throws ServletException, InterruptedException {
+        final Collector collector = new Collector();
+        try {
+            collector.init(new ServletConfig() {
+                @Override
+                public String getServletName() {
+                    return null;
+                }
+
+                @Override
+                public ServletContext getServletContext() {
+                    return null;
+                }
+
+                @Override
+                public String getInitParameter(final String name) {
+                    if (name.endsWith("period")) {
+                        return "100";
+                    }
+                    return "http://localhost:1234"; // agent-urls
+                }
+
+                @Override
+                public Enumeration<String> getInitParameterNames() {
+                    return null;
+                }
+            });
+
+            Thread.sleep(600);
+
+            final Collection<Counter> counters = Repository.INSTANCE.counters();
+            assertEquals(counters.toString(), 3, counters.size());
+
+            final Collection<Role> gauges = Repository.INSTANCE.gauges();
+            assertEquals(gauges.toString(), 3, gauges.size());
+
+            assertTrue(Repository.INSTANCE.statuses().containsKey("ubuntu"));
+        } finally {
+            collector.destroy();
+        }
+    }
+
+    public static class HttpServer {
+        private final String host;
+        private final int port;
+
+        private NioEventLoopGroup workerGroup;
+
+        public HttpServer(final String host, final int port) {
+            this.host = host;
+            this.port = port;
+        }
+
+        public HttpServer start() {
+            workerGroup = new NioEventLoopGroup(8);
+
+            try {
+                final ServerBootstrap bootstrap = new ServerBootstrap();
+                bootstrap
+                    .option(ChannelOption.SO_REUSEADDR, true)
+                    .option(ChannelOption.SO_SNDBUF, 1024)
+                    .option(ChannelOption.TCP_NODELAY, true)
+                    .group(workerGroup)
+                    .channel(NioServerSocketChannel.class)
+                    .childHandler(new Initializer())
+                    .bind(host, port).addListener(new ChannelFutureListener() {
+                        @Override
+                        public void operationComplete(final ChannelFuture future) throws Exception {
+                            if (!future.isSuccess()) {
+                                throw new MonitoringException("bind failed");
+                            }
+                        }
+                    }).sync();
+            } catch (final InterruptedException e) {
+                throw new MonitoringException(e);
+            }
+
+            return this;
+        }
+
+        public void stop() {
+            if (workerGroup != null) {
+                workerGroup.shutdownGracefully();
+            }
+        }
+
+        private static class Initializer extends ChannelInitializer<SocketChannel> {
+            @Override
+            protected void initChannel(final SocketChannel ch) throws Exception {
+                final ChannelPipeline pipeline = ch.pipeline();
+
+                pipeline
+                    .addLast("decoder", new HttpRequestDecoder())
+                    .addLast("aggregator", new HttpObjectAggregator(Integer.MAX_VALUE))
+                    .addLast("encoder", new HttpResponseEncoder())
+                    .addLast("chunked-writer", new ChunkedWriteHandler())
+                    .addLast("server", new RequestHandler());
+            }
+        }
+
+        private static class RequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
+            private AtomicBoolean done = new AtomicBoolean(false);
+
+            @Override
+            protected void channelRead0(final ChannelHandlerContext ctx, final FullHttpRequest fullHttpRequest) throws Exception {
+                if (done.get()) {
+                    ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.copiedBuffer("[]".getBytes())))
+                        .addListener(ChannelFutureListener.CLOSE);
+                    return;
+                }
+
+                done.set(true);
+                ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.copiedBuffer(("" +
+                    "[{\"type\": \"counter\",\"time\": \"2013-11-07T10:31:13Z\",\"data\": {\"min\":2.0,\"unit\":\"ns\",\"hits\":1,\"max\":2.0,\"marker\":\"ubuntu\",\"name\":\"counter#2\",\"concurrency\":0,\"m2\":0.0,\"sum\":2.0,\"mean\":2.0,\"role\":\"performances\",\"variance\":0.0}},{\"type\": \"counter\",\"time\": \"2013-11-07T10:31:13Z\",\"data\": {\"min\":0.0,\"unit\":\"ns\",\"hits\":1,\"max\":0.0,\"marker\":\"ubuntu\",\"name\":\"counter#0\",\"concurrency\":0,\"m2\":0.0,\"sum\":0.0,\"mean\":0.0,\"role\":\"performances\",\"variance\":0.0}},{\"type\": \"counter\",\"time\": \"2013-11-07T10:31:13Z\",\"data\": {\"min\":1.0,\"unit\":\"ns\",\"hits\":1,\"max\":1.0,\"marker\":\"ubuntu\",\"name\":\"counter#1\",\"concurrency\":0,\"m2\":0.0,\"sum\":1.0,\"mean\":1.0,\"role\":\"performances\",\"variance\":0.0}},{\"type\": \"gauge\",\"time\": \"2013-11-07T10:31:13Z\",\"data\": {\"unit\":\"u\",\"marker\":\"ubuntu\",\"value\":0.87,\"role\":\"CPU\"}},{\"type\": \"gauge\",\"time\": \"2013-11-07T1
 0:31:13Z\",\"data\": {\"unit\":\"u\",\"marker\":\"ubuntu\",\"value\":1.0245232E7,\"role\":\"Used Memory\"}},{\"type\": \"gauge\",\"time\": \"2013-11-07T10:31:13Z\",\"data\": {\"unit\":\"u\",\"marker\":\"ubuntu\",\"value\":0.0,\"role\":\"gaugerole\"}},{\"type\": \"validation\",\"time\": \"2013-11-07T10:31:13Z\",\"data\": {\"message\":\"descr\",\"marker\":\"ubuntu\",\"status\":\"OK\",\"name\":\"fake\"}},{\"type\": \"validation\",\"time\": \"2013-11-07T10:31:13Z\",\"data\": {\"message\":\"descr\",\"marker\":\"ubuntu\",\"status\":\"OK\",\"name\":\"refake\"}}]" +
+                    "").getBytes())))
+                    .addListener(ChannelFutureListener.CLOSE);
+            }
+        }
+    }
+}

Added: incubator/sirona/trunk/src/site/markdown/deployments.md
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/src/site/markdown/deployments.md?rev=1539590&view=auto
==============================================================================
--- incubator/sirona/trunk/src/site/markdown/deployments.md (added)
+++ incubator/sirona/trunk/src/site/markdown/deployments.md Thu Nov  7 10:50:38 2013
@@ -0,0 +1,85 @@
+<!---
+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.
+-->
+# Solutions
+
+Apache Sirona supports several deployments. Basically you can:
+
+* deploy everything locally (agent, reporting)
+* deploy agent in "client" JVMs and a remote collector ("server")
+* (not yet available - needs a custom persistent store) deploy client JVMs and twi servers: one for the collection and one for the reporting (GUI)
+* in agent/collector mode you can either use agent push mecanism or collector pulling
+
+## Everything locally
+
+TBD
+
+<pre class="prettyprint linenums"><![CDATA[
+<dependency>
+  <groupId>org.apache.sirona</groupId>
+  <artifactId>sirona-core</artifactId>
+  <version>${sirona.version}</version>
+</dependency>
+<dependency>
+  <groupId>org.apache.sirona</groupId>
+  <artifactId>sirona-jdbc</artifactId>
+  <version>${sirona.version}</version>
+</dependency>
+<dependency>
+  <groupId>org.apache.sirona</groupId>
+  <artifactId>sirona-jpa</artifactId>
+  <version>${sirona.version}</version>
+</dependency>
+<dependency>
+  <groupId>org.apache.sirona</groupId>
+  <artifactId>sirona-cdi</artifactId>
+  <version>${sirona.version}</version>
+</dependency>
+<dependency>
+  <groupId>org.apache.sirona</groupId>
+  <artifactId>sirona-jta</artifactId>
+  <version>${sirona.version}</version>
+</dependency>
+<dependency>
+  <groupId>org.apache.sirona</groupId>
+  <artifactId>sirona-web</artifactId>
+  <version>${sirona.version}</version>
+</dependency>
+<dependency>
+  <groupId>org.apache.sirona</groupId>
+  <artifactId>sirona-cube</artifactId>
+  <version>${sirona.version}</version>
+</dependency>
+<dependency>
+  <groupId>org.apache.sirona</groupId>
+  <artifactId>sirona-reporting</artifactId>
+  <version>${sirona.version}</version>
+  <classifier>classes</classifier>
+</dependency>
+...
+]]></pre>
+
+
+## Agent/Collector
+### Push mode
+
+TDB (cube datastore + collector)
+
+### Pull mode
+
+TDB (pull datastore + collector)

Modified: incubator/sirona/trunk/src/site/markdown/index.md
URL: http://svn.apache.org/viewvc/incubator/sirona/trunk/src/site/markdown/index.md?rev=1539590&r1=1539589&r2=1539590&view=diff
==============================================================================
--- incubator/sirona/trunk/src/site/markdown/index.md (original)
+++ incubator/sirona/trunk/src/site/markdown/index.md Thu Nov  7 10:50:38 2013
@@ -16,7 +16,7 @@ KIND, either express or implied.  See th
 specific language governing permissions and limitations
 under the License.
 -->
-## Commons Monitoring
+## Apache Sirona
 
 Commons-monitoring aims to provide a simple but extensible monitoring solution for Java applications.
 
@@ -26,6 +26,8 @@ How to start?
 
 [See Basis](./basis.html)
 
+[See Deployments](./deployments.html)
+
 [See Configuration](./configuration.html)
 
 [See Instrumentation](./instrumentation.html)