1 /* 2 * GangliaContext.java 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package org.apache.hadoop.metrics.ganglia; 22 23 import java.io.IOException; 24 import java.net.DatagramPacket; 25 import java.net.SocketAddress; 26 import java.net.UnknownHostException; 27 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 import org.apache.hadoop.conf.Configuration; 31 import org.apache.hadoop.metrics.ContextFactory; 32 import org.apache.hadoop.net.DNS; 33 34 /** 35 * Context for sending metrics to Ganglia version 3.1.x. 36 * 37 * 3.1.1 has a slightly different wire portal compared to 3.0.x. 38 */ 39 public class GangliaContext31 extends GangliaContext { 40 41 String hostName = "UNKNOWN.example.com"; 42 43 private static final Log LOG = 44 LogFactory.getLog("org.apache.hadoop.util.GangliaContext31"); 45 init(String contextName, ContextFactory factory)46 public void init(String contextName, ContextFactory factory) { 47 super.init(contextName, factory); 48 49 LOG.debug("Initializing the GangliaContext31 for Ganglia 3.1 metrics."); 50 51 // Take the hostname from the DNS class. 52 53 Configuration conf = new Configuration(); 54 55 if (conf.get("slave.host.name") != null) { 56 hostName = conf.get("slave.host.name"); 57 } else { 58 try { 59 hostName = DNS.getDefaultHost( 60 conf.get("dfs.datanode.dns.interface","default"), 61 conf.get("dfs.datanode.dns.nameserver","default")); 62 } catch (UnknownHostException uhe) { 63 LOG.error(uhe); 64 hostName = "UNKNOWN.example.com"; 65 } 66 } 67 } 68 emitMetric(String name, String type, String value)69 protected void emitMetric(String name, String type, String value) 70 throws IOException 71 { 72 if (name == null) { 73 LOG.warn("Metric was emitted with no name."); 74 return; 75 } else if (value == null) { 76 LOG.warn("Metric name " + name +" was emitted with a null value."); 77 return; 78 } else if (type == null) { 79 LOG.warn("Metric name " + name + ", value " + value + " has no type."); 80 return; 81 } 82 83 LOG.debug("Emitting metric " + name + ", type " + type + ", value " + 84 value + " from hostname" + hostName); 85 86 String units = getUnits(name); 87 int slope = getSlope(name); 88 int tmax = getTmax(name); 89 int dmax = getDmax(name); 90 offset = 0; 91 String groupName = name.substring(0,name.lastIndexOf(".")); 92 93 // The following XDR recipe was done through a careful reading of 94 // gm_protocol.x in Ganglia 3.1 and carefully examining the output of 95 // the gmetric utility with strace. 96 97 // First we send out a metadata message 98 xdr_int(128); // metric_id = metadata_msg 99 xdr_string(hostName); // hostname 100 xdr_string(name); // metric name 101 xdr_int(0); // spoof = False 102 xdr_string(type); // metric type 103 xdr_string(name); // metric name 104 xdr_string(units); // units 105 xdr_int(slope); // slope 106 xdr_int(tmax); // tmax, the maximum time between metrics 107 xdr_int(dmax); // dmax, the maximum data value 108 109 xdr_int(1); /*Num of the entries in extra_value field for 110 Ganglia 3.1.x*/ 111 xdr_string("GROUP"); /*Group attribute*/ 112 xdr_string(groupName); /*Group value*/ 113 114 for (SocketAddress socketAddress : metricsServers) { 115 DatagramPacket packet = 116 new DatagramPacket(buffer, offset, socketAddress); 117 datagramSocket.send(packet); 118 } 119 120 // Now we send out a message with the actual value. 121 // Technically, we only need to send out the metadata message once for 122 // each metric, but I don't want to have to record which metrics we did and 123 // did not send. 124 offset = 0; 125 xdr_int(133); // we are sending a string value 126 xdr_string(hostName); // hostName 127 xdr_string(name); // metric name 128 xdr_int(0); // spoof = False 129 xdr_string("%s"); // format field 130 xdr_string(value); // metric value 131 132 for (SocketAddress socketAddress : metricsServers) { 133 DatagramPacket packet = 134 new DatagramPacket(buffer, offset, socketAddress); 135 datagramSocket.send(packet); 136 } 137 } 138 139 } 140