PageRenderTime 36ms CodeModel.GetById 7ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/flume-core/src/test/java/com/cloudera/flume/reporter/ganglia/TestGangliaSink.java

#
Java | 295 lines | 184 code | 45 blank | 66 comment | 10 complexity | c953c1a1f2683e2a472629b07f4159cf MD5 | raw file
Possible License(s): Apache-2.0
  1. /**
  2. * Licensed to Cloudera, Inc. under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. Cloudera, Inc. licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. /**
  19. * Licensed to the Apache Software Foundation (ASF) under one
  20. * or more contributor license agreements. See the NOTICE file
  21. * distributed with this work for additional information
  22. * regarding copyright ownership. The ASF licenses this file
  23. * to you under the Apache License, Version 2.0 (the
  24. * "License"); you may not use this file except in compliance
  25. * with the License. You may obtain a copy of the License at
  26. *
  27. * http://www.apache.org/licenses/LICENSE-2.0
  28. *
  29. * Unless required by applicable law or agreed to in writing, software
  30. * distributed under the License is distributed on an "AS IS" BASIS,
  31. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  32. * See the License for the specific language governing permissions and
  33. * limitations under the License.
  34. */
  35. package com.cloudera.flume.reporter.ganglia;
  36. import static org.junit.Assert.assertTrue;
  37. import static org.junit.Assert.fail;
  38. import java.io.IOException;
  39. import java.net.DatagramPacket;
  40. import java.net.DatagramSocket;
  41. import java.util.concurrent.CountDownLatch;
  42. import java.util.concurrent.TimeUnit;
  43. import org.apache.log4j.Logger;
  44. import org.junit.Ignore;
  45. import org.junit.Test;
  46. import com.cloudera.flume.conf.Context;
  47. import com.cloudera.flume.conf.FlumeConfiguration;
  48. import com.cloudera.flume.conf.FlumeSpecException;
  49. import com.cloudera.flume.core.Attributes;
  50. import com.cloudera.flume.core.CompositeSink;
  51. import com.cloudera.flume.core.Event;
  52. import com.cloudera.flume.core.EventImpl;
  53. import com.cloudera.flume.core.EventSink;
  54. import com.cloudera.flume.core.FanOutSink;
  55. import com.cloudera.flume.core.Attributes.Type;
  56. import com.cloudera.util.Clock;
  57. import com.cloudera.util.NetUtils;
  58. /**
  59. * This is a test of the quick and dirty ganglia integration.
  60. */
  61. public class TestGangliaSink {
  62. private static final Logger LOG = Logger.getLogger(TestGangliaSink.class);
  63. // TODO (jon) Parens are invalid in metric names. (what other chars are
  64. // illegal in XDR Strings?
  65. String ATTR_LONG = "long test metric";
  66. String ATTR_INT = "int test metric";
  67. String ATTR_STRING = "string test metric";
  68. String ATTR_DOUBLE = "double test metric";
  69. /**
  70. * This test doesn't have a check, instead just it sends bogus data to an
  71. * actual ganglia gmond. This needs a human needs to verify.
  72. */
  73. @Ignore("Slow test, requires human to verify that values show up in ganglia")
  74. @Test
  75. public void sendDatatypesToGanglia_3_1_x() throws IOException,
  76. InterruptedException {
  77. // assumes there is a ganglia on local host
  78. // since using udp doesn't matter if it gets there or not.
  79. // default ganglia gmond multicast destination ip.
  80. String svrs = "239.2.11.71";
  81. EventSink lsnk = new GangliaSink(svrs, ATTR_LONG, "bytes", Type.LONG);
  82. EventSink isnk = new GangliaSink(svrs, ATTR_INT, "bytes", Type.INT);
  83. EventSink dsnk = new GangliaSink(svrs, ATTR_DOUBLE, "bytes", Type.DOUBLE);
  84. EventSink snk = new FanOutSink<EventSink>(lsnk, isnk, dsnk);
  85. snk.open();
  86. // This is enough for the data to register.
  87. for (int i = 0; i < 60; i++) {
  88. Event e = new EventImpl("".getBytes());
  89. Attributes.setLong(e, ATTR_LONG, i * 1000000);
  90. Attributes.setInt(e, ATTR_INT, (int) (i * 1000000));
  91. Attributes.setDouble(e, ATTR_DOUBLE, (double) (1.0 / (i % 20)));
  92. snk.append(e);
  93. Clock.sleep(1000);
  94. }
  95. snk.close();
  96. }
  97. @Test
  98. public void testBuilder() throws IOException, InterruptedException {
  99. EventSink snk = GangliaSink.builder().build(new Context(), "localhost",
  100. "foo", "int");
  101. for (int i = 0; i < 10; i++) {
  102. snk.open();
  103. snk.append(new EventImpl("".getBytes()));
  104. snk.close();
  105. }
  106. EventSink snk4 = GangliaSink.builder().build(new Context(), "localhost",
  107. "foo", "int", FlumeConfiguration.get().getGangliaServers());
  108. for (int i = 0; i < 10; i++) {
  109. snk4.open();
  110. snk4.append(new EventImpl("".getBytes()));
  111. snk4.close();
  112. }
  113. try {
  114. GangliaSink.builder().build(new Context(), "localhost", "foo", "bar");
  115. } catch (IllegalArgumentException e) {
  116. // expected a bad type ;
  117. return;
  118. }
  119. fail("expected failure");
  120. }
  121. @Test
  122. public void testFactoryBuild() throws FlumeSpecException, IOException,
  123. InterruptedException {
  124. EventSink snk = new CompositeSink(new Context(),
  125. "ganglia(\"localhost\", \"foo\", \"int\")");
  126. for (int i = 0; i < 10; i++) {
  127. snk.open();
  128. snk.append(new EventImpl("".getBytes()));
  129. snk.close();
  130. }
  131. }
  132. // //////////////////////////////////////////////////////////////////
  133. // This is ganglia >= 3.1.x wire format. Basically ripped out of
  134. // HADOOP-4675
  135. /**
  136. * This class is a runnable that will listen for Ganglia connections.
  137. */
  138. class GangliaSocketListener implements Runnable {
  139. private boolean isConfigured = false;
  140. private boolean hasData = false;
  141. private byte[] byteData;
  142. private int port;
  143. public CountDownLatch listening = new CountDownLatch(1);
  144. public CountDownLatch received = new CountDownLatch(1);
  145. public CountDownLatch done = new CountDownLatch(1);
  146. public void run() {
  147. DatagramSocket s;
  148. try {
  149. s = new DatagramSocket();
  150. setPort(s.getLocalPort());
  151. setConfigured(true);
  152. } catch (IOException e) {
  153. LOG.warn(e);
  154. // release all the latches
  155. listening.countDown();
  156. received.countDown();
  157. done.countDown();
  158. return;
  159. }
  160. listening.countDown();
  161. byte[] b = new byte[8192];
  162. DatagramPacket info = new DatagramPacket(b, b.length);
  163. try {
  164. s.receive(info);
  165. received.countDown();
  166. } catch (IOException e) {
  167. LOG.warn(e);
  168. return;
  169. }
  170. LOG.info("Got a new packet, length " + info.getLength());
  171. int bytesRead = info.getLength();
  172. if (bytesRead > 0)
  173. setHasData(true);
  174. byteData = new byte[info.getLength()];
  175. System.arraycopy(info.getData(), 0, byteData, 0, bytesRead);
  176. done.countDown();
  177. }
  178. public void setConfigured(boolean isConfigured) {
  179. this.isConfigured = isConfigured;
  180. }
  181. public boolean getConfigured() {
  182. return isConfigured;
  183. }
  184. public void setHasData(boolean hasData) {
  185. this.hasData = hasData;
  186. }
  187. public boolean getHasData() {
  188. return hasData;
  189. }
  190. public byte[] getBytes() {
  191. return byteData;
  192. }
  193. public void setPort(int port) {
  194. this.port = port;
  195. }
  196. public int getPort() {
  197. return port;
  198. }
  199. }
  200. /**
  201. * This test was originally stolen and hacked from hadoop's
  202. * TestGangliaContext31. It has been modified to use latches as
  203. * synchronization mechanism -- the previous implementation's synchronization
  204. * mechanisms were unreliable.
  205. */
  206. @Test
  207. public void testGanglia31Metrics() throws IOException, InterruptedException {
  208. String hostName = NetUtils.localhost();
  209. GangliaSocketListener listener = new GangliaSocketListener();
  210. Thread listenerThread = new Thread(listener);
  211. listenerThread.start();
  212. assertTrue("Took too long to bind to a port", listener.listening.await(5,
  213. TimeUnit.SECONDS));
  214. LOG.info("Listening to port " + listener.getPort());
  215. // setup and send some ganglia data.
  216. EventSink ganglia = new GangliaSink(hostName + ":" + listener.getPort(),
  217. "foo", "bars", Type.INT);
  218. ganglia.open();
  219. Event e = new EventImpl("baz".getBytes());
  220. Attributes.setInt(e, "foo", 1337);
  221. ganglia.append(e);
  222. ganglia.close();
  223. // did the other thread get the data?
  224. assertTrue("Took too long to recieve a packet", listener.received.await(5,
  225. TimeUnit.SECONDS));
  226. // and then parsed it?
  227. assertTrue("Did not receive proper packet", listener.done.await(5,
  228. TimeUnit.SECONDS));
  229. assertTrue("Did not recieve Ganglia data", listener.getHasData());
  230. byte[] hostNameBytes = hostName.getBytes();
  231. byte[] xdrBytes = listener.getBytes();
  232. // Make sure that the received bytes from Ganglia has the correct
  233. // hostname for this host
  234. boolean hasHostname = false;
  235. LOG.info("Checking to make sure that the Ganglia data contains host "
  236. + hostName);
  237. for (int i = 0; i < xdrBytes.length - hostNameBytes.length; i++) {
  238. hasHostname = true;
  239. for (int j = 0; j < hostNameBytes.length; j++) {
  240. if (xdrBytes[i + j] != hostNameBytes[j]) {
  241. hasHostname = false;
  242. break;
  243. }
  244. }
  245. if (hasHostname)
  246. break;
  247. }
  248. assertTrue("Did not correctly resolve hostname in Ganglia", hasHostname);
  249. }
  250. }