You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by rm...@apache.org on 2013/10/16 11:00:03 UTC
svn commit: r1532693 - in /commons/sandbox/monitoring/trunk: ./ cube/
cube/src/ cube/src/main/ cube/src/main/java/ cube/src/main/java/org/
cube/src/main/java/org/apache/ cube/src/main/java/org/apache/commons/
cube/src/main/java/org/apache/commons/monit...
Author: rmannibucau
Date: Wed Oct 16 09:00:02 2013
New Revision: 1532693
URL: http://svn.apache.org/r1532693
Log:
adding a cube module to push to square cube
Added:
commons/sandbox/monitoring/trunk/cube/
commons/sandbox/monitoring/trunk/cube/pom.xml
commons/sandbox/monitoring/trunk/cube/src/
commons/sandbox/monitoring/trunk/cube/src/main/
commons/sandbox/monitoring/trunk/cube/src/main/java/
commons/sandbox/monitoring/trunk/cube/src/main/java/org/
commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/
commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/
commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/
commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/
commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/Cube.java
commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeBuilder.java
commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeDataStore.java
commons/sandbox/monitoring/trunk/cube/src/test/
commons/sandbox/monitoring/trunk/cube/src/test/java/
commons/sandbox/monitoring/trunk/cube/src/test/java/org/
commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/
commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/
commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/
commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/
commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeDataStoreTest.java
commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeServer.java
commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/gauge/
commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/gauge/MockGauge.java
commons/sandbox/monitoring/trunk/cube/src/test/resources/
commons/sandbox/monitoring/trunk/cube/src/test/resources/META-INF/
commons/sandbox/monitoring/trunk/cube/src/test/resources/META-INF/services/
commons/sandbox/monitoring/trunk/cube/src/test/resources/META-INF/services/org.apache.commons.monitoring.gauges.Gauge
commons/sandbox/monitoring/trunk/cube/src/test/resources/commons-monitoring.properties
- copied, changed from r1532645, commons/sandbox/monitoring/trunk/graphite/src/test/resources/commons-monitoring.properties
commons/sandbox/monitoring/trunk/src/site/markdown/cube.md
- copied, changed from r1532645, commons/sandbox/monitoring/trunk/src/site/markdown/graphite.md
Modified:
commons/sandbox/monitoring/trunk/pom.xml
commons/sandbox/monitoring/trunk/src/site/markdown/index.md
Added: commons/sandbox/monitoring/trunk/cube/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/cube/pom.xml?rev=1532693&view=auto
==============================================================================
--- commons/sandbox/monitoring/trunk/cube/pom.xml (added)
+++ commons/sandbox/monitoring/trunk/cube/pom.xml Wed Oct 16 09:00:02 2013
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>commons-monitoring-parent</artifactId>
+ <groupId>org.apache.commons.monitoring</groupId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>commons-monitoring-cube</artifactId>
+ <name>Commons Monitoring (Sandbox) :: Cube</name>
+ <description>A DataStore for https://github.com/square/cube</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.commons.monitoring</groupId>
+ <artifactId>commons-monitoring-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-codec-http</artifactId>
+ <version>4.0.9.Final</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
Added: commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/Cube.java
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/Cube.java?rev=1532693&view=auto
==============================================================================
--- commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/Cube.java (added)
+++ commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/Cube.java Wed Oct 16 09:00:02 2013
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.monitoring.cube;
+
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.URL;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class Cube {
+ private static final Logger LOGGER = Logger.getLogger(Cube.class.getName());
+
+ 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 final CubeBuilder config;
+ private final Proxy proxy;
+
+ public Cube(final CubeBuilder cubeBuilder) {
+ config = cubeBuilder;
+ if (config.getProxyHost() != null) {
+ proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(config.getProxyHost(), config.getProxyPort()));
+ } else {
+ proxy = Proxy.NO_PROXY;
+ }
+ }
+
+ public void post(final String payload) {
+ try {
+ final URL url = new URL(config.getCollector());
+
+ final HttpURLConnection connection = HttpURLConnection.class.cast(url.openConnection(proxy));
+ connection.setRequestMethod(POST);
+ connection.setRequestProperty(CONTENT_TYPE, APPLICATION_JSON);
+ connection.setRequestProperty(CONTENT_LENGTH, Long.toString(payload.length()));
+ connection.setUseCaches(false);
+ connection.setDoInput(true);
+ connection.setDoOutput(true);
+
+ try {
+ final OutputStream output = connection.getOutputStream();
+ try {
+ output.write(payload.getBytes());
+ output.flush();
+
+ final int status = connection.getResponseCode();
+ if (status / 100 != 2) {
+ LOGGER.warning("Pushed data but response code is: " + status);
+ }
+ } finally {
+ if (output != null) {
+ output.close();
+ }
+ }
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ } catch (final Exception e) {
+ LOGGER.log(Level.WARNING, "Can't post data to collector", e);
+ }
+ }
+}
Added: commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeBuilder.java
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeBuilder.java?rev=1532693&view=auto
==============================================================================
--- commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeBuilder.java (added)
+++ commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeBuilder.java Wed Oct 16 09:00:02 2013
@@ -0,0 +1,47 @@
+/*
+ * 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.commons.monitoring.cube;
+
+import org.apache.commons.monitoring.configuration.Configuration;
+
+@Configuration.AutoSet
+public class CubeBuilder {
+ private String proxyHost;
+ private int proxyPort;
+ private String collector;
+
+ public Cube build() {
+ return new Cube(this);
+ }
+
+ public String getProxyHost() {
+ return proxyHost;
+ }
+
+ public int getProxyPort() {
+ return proxyPort;
+ }
+
+ public String getCollector() {
+ return collector;
+ }
+
+ @Override
+ public String toString() {
+ return "CubeBuilder{" + collector + '}';
+ }
+}
Added: commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeDataStore.java
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeDataStore.java?rev=1532693&view=auto
==============================================================================
--- commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeDataStore.java (added)
+++ commons/sandbox/monitoring/trunk/cube/src/main/java/org/apache/commons/monitoring/cube/CubeDataStore.java Wed Oct 16 09:00:02 2013
@@ -0,0 +1,165 @@
+/*
+ * 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.commons.monitoring.cube;
+
+import org.apache.commons.monitoring.Role;
+import org.apache.commons.monitoring.configuration.Configuration;
+import org.apache.commons.monitoring.counters.Counter;
+import org.apache.commons.monitoring.counters.MetricData;
+import org.apache.commons.monitoring.gauges.Gauge;
+import org.apache.commons.monitoring.repositories.Repository;
+import org.apache.commons.monitoring.store.BatchCounterDataStore;
+import org.apache.commons.monitoring.store.GaugeValuesRequest;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+public class CubeDataStore extends BatchCounterDataStore {
+ private static final String JSON_BASE = "{" +
+ "\"type\": \"%s\"," +
+ "\"time\": \"%s\"," +
+ "\"data\": %s" +
+ "}";
+
+ private static final String GAUGE_TYPE = "gauge";
+ private static final String COUNTER_TYPE = "counter";
+ private static final String JS_ISO_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+ private static final String UTC = "UTC";
+
+ private final Cube cube = Configuration.findOrCreateInstance(CubeBuilder.class).build();
+
+ private final BlockingQueue<DateFormat> isoDateFormatters;
+
+ public CubeDataStore() {
+ final int maxConcurrency = 2 * Runtime.getRuntime().availableProcessors();
+ isoDateFormatters = new ArrayBlockingQueue<DateFormat>(maxConcurrency);
+ for (int i = 0; i < maxConcurrency; i++) {
+ isoDateFormatters.add(newIsoDateFormatter());
+ }
+ }
+
+ @Override
+ protected synchronized void pushCountersByBatch(final Repository instance) {
+ final long ts = System.currentTimeMillis();
+ final StringBuilder events = new StringBuilder();
+ for (final Counter counter : instance) {
+ final MapBuilder data = new MapBuilder()
+ .add("name", counter.getKey().getName())
+ .add("role", counter.getKey().getRole().getName());
+
+ for (final MetricData metric : MetricData.values()) {
+ final double value = metric.value(counter);
+ if (!Double.isNaN(value) && !Double.isInfinite(value)) {
+ data.add(metric.name(), value);
+ }
+ }
+
+ buildEvent(events, COUNTER_TYPE, ts, data.map()).append(',');
+ }
+ if (events.length() > 0) {
+ events.setLength(events.length() - 1);
+ cube.post(finalPayload(events));
+ }
+ }
+
+ @Override
+ public void addToGauge(final Gauge gauge, final long time, final double value) {
+ final Role role = gauge.role();
+
+ cube.post(finalPayload(
+ buildEvent(new StringBuilder(), GAUGE_TYPE, time,
+ new MapBuilder()
+ .add("value", value)
+ .add("role", role.getName())
+ .add("unit", role.getUnit().getName())
+ .map())));
+ }
+
+ @Override
+ public Map<Long, Double> getGaugeValues(final GaugeValuesRequest gaugeValuesRequest) {
+ return Collections.emptyMap(); // TODO: maybe query cube?
+ }
+
+ private static String finalPayload(final StringBuilder events) {
+ return '[' + events.toString() + ']';
+ }
+
+ private StringBuilder buildEvent(final StringBuilder builder, final String type, final long time, final Map<String, Object> data) {
+ return builder.append(String.format(JSON_BASE, type, isoDate(time), buildData(data)));
+ }
+
+ private String isoDate(final long time) {
+ final Date date = new Date(time);
+
+ DateFormat formatter = null;
+ try {
+ formatter = isoDateFormatters.take();
+ return formatter.format(date);
+ } catch (final InterruptedException e) {
+ return newIsoDateFormatter().format(date);
+ } finally {
+ if (formatter != null) {
+ isoDateFormatters.add(formatter);
+ }
+ }
+ }
+
+ private static String buildData(final Map<String, Object> data) {
+ final StringBuilder builder = new StringBuilder().append("{");
+ for (final Map.Entry<String, Object> entry : data.entrySet()) {
+ builder.append('\"').append(entry.getKey()).append('\"').append(':');
+
+ final Object value = entry.getValue();
+ if (String.class.isInstance(value)) {
+ builder.append('\"').append(value).append('\"');
+ } else {
+ builder.append(value);
+ }
+
+ builder.append(',');
+ }
+ builder.setLength(builder.length() - 1);
+ return builder.append("}").toString();
+ }
+
+ private static DateFormat newIsoDateFormatter() {
+ final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(JS_ISO_FORMAT, Locale.ENGLISH);
+ simpleDateFormat.setTimeZone(TimeZone.getTimeZone(UTC));
+ return simpleDateFormat;
+ }
+
+ private static class MapBuilder {
+ private final Map<String, Object> map = new HashMap<String, Object>();
+
+ public MapBuilder add(final String key, final Object value) {
+ map.put(key, value);
+ return this;
+ }
+
+ public Map<String, Object> map() {
+ return map;
+ }
+ }
+}
Added: commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeDataStoreTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeDataStoreTest.java?rev=1532693&view=auto
==============================================================================
--- commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeDataStoreTest.java (added)
+++ commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeDataStoreTest.java Wed Oct 16 09:00:02 2013
@@ -0,0 +1,90 @@
+/*
+ * 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.commons.monitoring.cube;
+
+import org.apache.commons.monitoring.Role;
+import org.apache.commons.monitoring.counters.Counter;
+import org.apache.commons.monitoring.gauges.Gauge;
+import org.apache.commons.monitoring.repositories.Repository;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class CubeDataStoreTest {
+ private CubeServer server;
+ private Gauge.LoaderHelper gauges;
+
+ @Before
+ public void startCube() throws IOException {
+ server = new CubeServer("localhost", 1234).start();
+ Repository.INSTANCE.clear();
+ gauges = new Gauge.LoaderHelper(false);
+ }
+
+ @After
+ public void stopCube() {
+ gauges.destroy();
+ Repository.INSTANCE.clear();
+ server.stop();
+ }
+
+ @Test
+ public void store() throws InterruptedException {
+ { // force some counter data
+ final Counter counter = Repository.INSTANCE.getCounter(new Counter.Key(Role.PERFORMANCES, "test"));
+ counter.add(1.4);
+ counter.add(1.6);
+ Thread.sleep(150);
+ counter.add(2.3);
+ counter.add(2.9);
+ Thread.sleep(150);
+ }
+
+ final Collection<String> messages = server.getMessages();
+ final Collection<String> gauges = new ArrayList<String>(4);
+ int counters = 0;
+ String aCounterMessage = null;
+ for (final String m : messages) {
+ if (m.contains("\"type\": \"gauge\"")) {
+ gauges.add(m.replaceAll("\"time\": \"[^\"]*\"", "\"time\": \"-\"")); // remove date to be able to test it easily
+ } else {
+ counters++;
+ aCounterMessage = m;
+ }
+ }
+
+ assertTrue(gauges.contains("[{\"type\": \"gauge\",\"time\": \"-\",\"data\": {\"unit\":\"u\",\"value\":0.0,\"role\":\"mock\"}}]"));
+ assertTrue(gauges.contains("[{\"type\": \"gauge\",\"time\": \"-\",\"data\": {\"unit\":\"u\",\"value\":1.0,\"role\":\"mock\"}}]"));
+ assertTrue(gauges.contains("[{\"type\": \"gauge\",\"time\": \"-\",\"data\": {\"unit\":\"u\",\"value\":2.0,\"role\":\"mock\"}}]"));
+ assertTrue(gauges.contains("[{\"type\": \"gauge\",\"time\": \"-\",\"data\": {\"unit\":\"u\",\"value\":3.0,\"role\":\"mock\"}}]"));
+
+ assertNotNull(aCounterMessage);
+ assertThat(aCounterMessage, containsString("Variance"));
+ assertThat(aCounterMessage, containsString("Value"));
+ assertThat(aCounterMessage, containsString("Hits"));
+ assertThat(aCounterMessage, containsString("Sum"));
+ }
+}
Added: commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeServer.java
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeServer.java?rev=1532693&view=auto
==============================================================================
--- commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeServer.java (added)
+++ commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/CubeServer.java Wed Oct 16 09:00:02 2013
@@ -0,0 +1,175 @@
+/*
+ * 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.commons.monitoring.cube;
+
+import io.netty.bootstrap.ServerBootstrap;
+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.HttpMethod;
+import io.netty.handler.codec.http.HttpObjectAggregator;
+import io.netty.handler.codec.http.HttpRequestDecoder;
+import io.netty.handler.codec.http.HttpResponse;
+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 java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class CubeServer {
+ private static final Logger LOGGER = Logger.getLogger(CubeServer.class.getName());
+
+ private final String host;
+ private final int port;
+
+ private NioEventLoopGroup workerGroup;
+ private final Collection<String> messages = new LinkedList<String>();
+
+ public CubeServer(final String host, final int port) {
+ this.host = host;
+ if (port <= 0) { // generate a port
+ this.port = findNextAvailablePort();
+ } else {
+ this.port = port;
+ }
+ }
+
+ public Collection<String> getMessages() {
+ synchronized (messages) {
+ return new ArrayList<String>(messages);
+ }
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ private static int findNextAvailablePort() {
+ ServerSocket serverSocket = null;
+ try {
+ serverSocket = new ServerSocket(0);
+ return serverSocket.getLocalPort();
+ } catch (final IOException e) {
+ LOGGER.log(Level.SEVERE, e.getMessage(), e);
+ } finally {
+ if (serverSocket != null) {
+ try {
+ serverSocket.close();
+ } catch (final IOException e) {
+ // no-op
+ }
+ }
+ }
+ return 0;
+ }
+
+ public CubeServer 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(messages))
+ .bind(host, port).addListener(new ChannelFutureListener() {
+ @Override
+ public void operationComplete(final ChannelFuture future) throws Exception {
+ if (!future.isSuccess()) {
+ LOGGER.severe("Can't start HTTP server");
+ } else {
+ LOGGER.info(String.format("Server started on http://%s:%s", host, port));
+ }
+ }
+ }).sync();
+ } catch (final InterruptedException e) {
+ LOGGER.log(Level.SEVERE, e.getMessage(), e);
+ }
+
+ return this;
+ }
+
+ public void stop() {
+ if (workerGroup != null) {
+ workerGroup.shutdownGracefully();
+ LOGGER.info(String.format("Server http://%s:%s stopped", host, port));
+ }
+ }
+
+ private static class Initializer extends ChannelInitializer<SocketChannel> {
+ private final Collection<String> messages;
+
+ private Initializer(final Collection<String> messages) {
+ this.messages = messages;
+ }
+
+ @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("featured-mock-server", new RequestHandler(messages));
+ }
+ }
+
+ private static class RequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
+ private final Collection<String> messages;
+
+ private RequestHandler(final Collection<String> messages) {
+ this.messages = messages;
+ }
+
+ @Override
+ protected void channelRead0(final ChannelHandlerContext ctx, final FullHttpRequest fullHttpRequest) throws Exception {
+ final ChannelFuture future;
+ if (HttpMethod.POST.equals(fullHttpRequest.getMethod())) {
+ synchronized (messages) {
+ messages.add(new String(fullHttpRequest.content().array()));
+ }
+ final HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
+ future = ctx.writeAndFlush(response);
+ } else {
+ LOGGER.warning("Received " + fullHttpRequest.getMethod());
+ future = ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR));
+ }
+ future.addListener(ChannelFutureListener.CLOSE);
+ }
+ }
+}
\ No newline at end of file
Added: commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/gauge/MockGauge.java
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/gauge/MockGauge.java?rev=1532693&view=auto
==============================================================================
--- commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/gauge/MockGauge.java (added)
+++ commons/sandbox/monitoring/trunk/cube/src/test/java/org/apache/commons/monitoring/cube/gauge/MockGauge.java Wed Oct 16 09:00:02 2013
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.monitoring.cube.gauge;
+
+import org.apache.commons.monitoring.Role;
+import org.apache.commons.monitoring.counters.Unit;
+import org.apache.commons.monitoring.gauges.Gauge;
+
+public class MockGauge implements Gauge {
+ public static final Role MOCK = new Role("mock", Unit.UNARY);
+
+ private int count = 0;
+
+ @Override
+ public Role role() {
+ return MOCK;
+ }
+
+ @Override
+ public double value() {
+ return count++;
+ }
+
+ @Override
+ public long period() {
+ return 100;
+ }
+}
Added: commons/sandbox/monitoring/trunk/cube/src/test/resources/META-INF/services/org.apache.commons.monitoring.gauges.Gauge
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/cube/src/test/resources/META-INF/services/org.apache.commons.monitoring.gauges.Gauge?rev=1532693&view=auto
==============================================================================
--- commons/sandbox/monitoring/trunk/cube/src/test/resources/META-INF/services/org.apache.commons.monitoring.gauges.Gauge (added)
+++ commons/sandbox/monitoring/trunk/cube/src/test/resources/META-INF/services/org.apache.commons.monitoring.gauges.Gauge Wed Oct 16 09:00:02 2013
@@ -0,0 +1 @@
+org.apache.commons.monitoring.cube.gauge.MockGauge
Copied: commons/sandbox/monitoring/trunk/cube/src/test/resources/commons-monitoring.properties (from r1532645, commons/sandbox/monitoring/trunk/graphite/src/test/resources/commons-monitoring.properties)
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/cube/src/test/resources/commons-monitoring.properties?p2=commons/sandbox/monitoring/trunk/cube/src/test/resources/commons-monitoring.properties&p1=commons/sandbox/monitoring/trunk/graphite/src/test/resources/commons-monitoring.properties&r1=1532645&r2=1532693&rev=1532693&view=diff
==============================================================================
--- commons/sandbox/monitoring/trunk/graphite/src/test/resources/commons-monitoring.properties (original)
+++ commons/sandbox/monitoring/trunk/cube/src/test/resources/commons-monitoring.properties Wed Oct 16 09:00:02 2013
@@ -14,9 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-org.apache.commons.monitoring.store.DataStore = org.apache.commons.monitoring.graphite.GraphiteDataStore
-
-org.apache.commons.monitoring.graphite.period = 100
-
-org.apache.commons.monitoring.graphite.GraphiteBuilder.address = localhost
-org.apache.commons.monitoring.graphite.GraphiteBuilder.port = 1234
+org.apache.commons.monitoring.store.DataStore = org.apache.commons.monitoring.cube.CubeDataStore
+org.apache.commons.monitoring.cube.period = 100
+org.apache.commons.monitoring.cube.CubeBuilder.collector = http://localhost:1234/collector/1.0/event/put
Modified: commons/sandbox/monitoring/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/pom.xml?rev=1532693&r1=1532692&r2=1532693&view=diff
==============================================================================
--- commons/sandbox/monitoring/trunk/pom.xml (original)
+++ commons/sandbox/monitoring/trunk/pom.xml Wed Oct 16 09:00:02 2013
@@ -56,6 +56,7 @@
<module>web</module>
<module>reporting</module>
<module>graphite</module>
+ <module>cube</module>
</modules>
<developers>
Copied: commons/sandbox/monitoring/trunk/src/site/markdown/cube.md (from r1532645, commons/sandbox/monitoring/trunk/src/site/markdown/graphite.md)
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/src/site/markdown/cube.md?p2=commons/sandbox/monitoring/trunk/src/site/markdown/cube.md&p1=commons/sandbox/monitoring/trunk/src/site/markdown/graphite.md&r1=1532645&r2=1532693&rev=1532693&view=diff
==============================================================================
--- commons/sandbox/monitoring/trunk/src/site/markdown/graphite.md (original)
+++ commons/sandbox/monitoring/trunk/src/site/markdown/cube.md Wed Oct 16 09:00:02 2013
@@ -16,38 +16,42 @@ KIND, either express or implied. See th
specific language governing permissions and limitations
under the License.
-->
-# Graphite
+# Cube
-Graphite module allows to push counters and gauges to a graphite instance.
+Cube module allows to push counters and gauges to a Square Cube instance (see [Cube github wiki](https://github.com/square/cube/wiki)).
## Configuration
-* `org.apache.commons.monitoring.graphite.GraphiteBuilder.address`: the graphite instance host/IP
-* `org.apache.commons.monitoring.graphite.GraphiteBuilder.port`: the graphite instance port
-* `org.apache.commons.monitoring.graphite.GraphiteBuilder.charset`: the charset to use with this Graphite instance
+org.apache.commons.monitoring.store.DataStore = org.apache.commons.monitoring.cube.CubeDataStore
+org.apache.commons.monitoring.cube.period = 100
+org.apache.commons.monitoring.cube.CubeBuilder.collector = http://localhost:1234/collector/1.0/event/put
+* `org.apache.commons.monitoring.cube.CubeBuilder.collector`: the cube event collector address (`http://xxx:1234/collector/1.0/event/put` for instance)
+* `org.apache.commons.monitoring.cube.CubeBuilder.proxyHost`: optionally a proxy host
+* `org.apache.commons.monitoring.cube.CubeBuilder.proxyPort`: optionally a proxy port
For instance your `commons-monitoring.properties` can look like:
```
-org.apache.commons.monitoring.graphite.GraphiteBuilder.address = localhost
-org.apache.commons.monitoring.graphite.GraphiteBuilder.port = 1234
+org.apache.commons.monitoring.cube.CubeBuilder.collector = http://localhost:1234/collector/1.0/event/put
```
+
## DataStore
-To push metrics (Gauges + Counters) to Graphite you can use the dedicated `DataStore`: `org.apache.commons.monitoring.graphite.GraphiteDataStore`.
+To push metrics (Gauges + Counters) to Graphite you can use the dedicated `DataStore`: `org.apache.commons.monitoring.cube.CubeDataStore`.
Simply add to `commons-monitoring.properties` the line:
```
-org.apache.commons.monitoring.store.DataStore = org.apache.commons.monitoring.graphite.GraphiteDataStore
+org.apache.commons.monitoring.store.DataStore = org.apache.commons.monitoring.cube.CubeDataStore
```
### Counters
You can also configure the period used to flush counters values:
-* `org.apache.commons.monitoring.graphite.period`: which period to use to push counters data to Graphite (default to 1mn).
+* `org.apache.commons.monitoring.cube.period`: which period to use to push counters data to Graphite (default to 1mn).
+
+## Limitations (ATM)
-## Limitations
+When using CubeDataStore you cannot retrieve locally gauges values (you are expected to use Cube for it).
-When using GraphiteDataStore you cannot retrieve locally gauges values (you are expected to use Graphite for it).
Modified: commons/sandbox/monitoring/trunk/src/site/markdown/index.md
URL: http://svn.apache.org/viewvc/commons/sandbox/monitoring/trunk/src/site/markdown/index.md?rev=1532693&r1=1532692&r2=1532693&view=diff
==============================================================================
--- commons/sandbox/monitoring/trunk/src/site/markdown/index.md (original)
+++ commons/sandbox/monitoring/trunk/src/site/markdown/index.md Wed Oct 16 09:00:02 2013
@@ -38,4 +38,8 @@ How to start?
[See Web](./web.html)
+[See Graphite](./graphite.html)
+
+[See Cube](./cube.html)
+