001/*
002 * GangliaContext.java
003 *
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *     http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020
021package org.apache.hadoop.metrics.ganglia;
022
023import java.io.IOException;
024import java.net.DatagramPacket;
025import java.net.SocketAddress;
026import java.net.UnknownHostException;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.apache.hadoop.conf.Configuration;
031import org.apache.hadoop.metrics.ContextFactory;
032import org.apache.hadoop.net.DNS;
033
034/**
035 * Context for sending metrics to Ganglia version 3.1.x.
036 * 
037 * 3.1.1 has a slightly different wire portal compared to 3.0.x.
038 *
039 * @deprecated Use {@link org.apache.hadoop.metrics2.sink.ganglia.GangliaSink31}
040 * instead.
041 */
042@Deprecated
043public class GangliaContext31 extends GangliaContext {
044
045  String hostName = "UNKNOWN.example.com";
046
047  private static final Log LOG = 
048    LogFactory.getLog("org.apache.hadoop.util.GangliaContext31");
049
050  public void init(String contextName, ContextFactory factory) {
051    super.init(contextName, factory);
052
053    LOG.debug("Initializing the GangliaContext31 for Ganglia 3.1 metrics.");
054
055    // Take the hostname from the DNS class.
056
057    Configuration conf = new Configuration();
058
059    if (conf.get("slave.host.name") != null) {
060      hostName = conf.get("slave.host.name");
061    } else {
062      try {
063        hostName = DNS.getDefaultHost(
064          conf.get("dfs.datanode.dns.interface","default"),
065          conf.get("dfs.datanode.dns.nameserver","default"));
066      } catch (UnknownHostException uhe) {
067        LOG.error(uhe);
068        hostName = "UNKNOWN.example.com";
069      }
070    }
071  }
072
073  protected void emitMetric(String name, String type,  String value) 
074    throws IOException
075  {
076    if (name == null) {
077      LOG.warn("Metric was emitted with no name.");
078      return;
079    } else if (value == null) {
080      LOG.warn("Metric name " + name +" was emitted with a null value.");
081      return;
082    } else if (type == null) {
083      LOG.warn("Metric name " + name + ", value " + value + " has no type.");
084      return;
085    }
086
087    if (LOG.isDebugEnabled()) {
088      LOG.debug("Emitting metric " + name + ", type " + type + ", value " +
089          value + " from hostname" + hostName);
090    }
091
092    String units = getUnits(name);
093    int slope = getSlope(name);
094    int tmax = getTmax(name);
095    int dmax = getDmax(name);
096    offset = 0;
097    String groupName = name.substring(0,name.lastIndexOf("."));
098
099    // The following XDR recipe was done through a careful reading of
100    // gm_protocol.x in Ganglia 3.1 and carefully examining the output of
101    // the gmetric utility with strace.
102
103    // First we send out a metadata message
104    xdr_int(128);         // metric_id = metadata_msg
105    xdr_string(hostName); // hostname
106    xdr_string(name);     // metric name
107    xdr_int(0);           // spoof = False
108    xdr_string(type);     // metric type
109    xdr_string(name);     // metric name
110    xdr_string(units);    // units
111    xdr_int(slope);       // slope
112    xdr_int(tmax);        // tmax, the maximum time between metrics
113    xdr_int(dmax);        // dmax, the maximum data value
114
115    xdr_int(1);             /*Num of the entries in extra_value field for 
116                              Ganglia 3.1.x*/
117    xdr_string("GROUP");    /*Group attribute*/
118    xdr_string(groupName);  /*Group value*/
119
120    for (SocketAddress socketAddress : metricsServers) {
121      DatagramPacket packet =
122        new DatagramPacket(buffer, offset, socketAddress);
123      datagramSocket.send(packet);
124    }
125
126    // Now we send out a message with the actual value.
127    // Technically, we only need to send out the metadata message once for
128    // each metric, but I don't want to have to record which metrics we did and
129    // did not send.
130    offset = 0;
131    xdr_int(133);         // we are sending a string value
132    xdr_string(hostName); // hostName
133    xdr_string(name);     // metric name
134    xdr_int(0);           // spoof = False
135    xdr_string("%s");     // format field
136    xdr_string(value);    // metric value
137        
138    for (SocketAddress socketAddress : metricsServers) {
139      DatagramPacket packet = 
140        new DatagramPacket(buffer, offset, socketAddress);
141      datagramSocket.send(packet);
142    }
143  }
144
145}