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)