com.scaleunlimited.cascading.GangliaFlowReporter.java Source code

Java tutorial

Introduction

Here is the source code for com.scaleunlimited.cascading.GangliaFlowReporter.java

Source

/**
 * Copyright 2010 TransPac Software, Inc.
 * 
 * Licensed 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 com.scaleunlimited.cascading;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;

import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.metrics.ContextFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class GangliaFlowReporter implements IFlowReporter {
    private static final Logger LOGGER = LoggerFactory.getLogger(GangliaFlowReporter.class);

    private static final int GANGLIA_DEFAULT_PORT = 8649;
    private final static int GANGLIA_SLOPE_UNSPECIFIED = 4;
    private final static String GANGLIA_VALUE_STRING = "string";

    private InetAddress _address;
    private int _port;

    public GangliaFlowReporter() {
        String serverPort = getDefaultServerPort();
        if (serverPort != null) {
            String server = null;
            int index = serverPort.indexOf(":");
            if (index != -1) { // we assume the string is of the type name:port
                String portStr = serverPort.substring(index + 1);
                _port = Integer.parseInt(portStr);
            } else {
                server = serverPort;
                _port = GANGLIA_DEFAULT_PORT;
            }
            try {
                _address = InetAddress.getByName(server);
            } catch (UnknownHostException e) {
                LOGGER.info("Unable to resolve server name: " + server);
                _address = null;
            }
        }
    }

    public GangliaFlowReporter(InetAddress address, int port) {
        _address = address;
        _port = port;
    }

    @Override
    public void setStatus(Level level, String msg) {
        if (_address != null) {
            sendToGanglia(_address, _port, level.toString(), msg, GANGLIA_VALUE_STRING, "",
                    GANGLIA_SLOPE_UNSPECIFIED, 100, 100);
        }
    }

    @Override
    public void setStatus(String msg, Throwable t) {
        if (_address != null) {
            sendToGanglia(_address, _port, "Throwable", msg, GANGLIA_VALUE_STRING, "", GANGLIA_SLOPE_UNSPECIFIED,
                    100, 100);
        }
    }

    private boolean isLocalJob() {
        JobConf jobConf = new JobConf();
        return jobConf.get("mapred.job.tracker").equalsIgnoreCase("local");
    }

    private String getDefaultServerPort() {
        String serverPort = null;

        try {
            ContextFactory contextFactory = ContextFactory.getFactory();
            serverPort = (String) contextFactory.getAttribute("mapred.servers");
        } catch (IOException e) {
            if (isLocalJob()) {
                // Only log an error when not running in local mode
                LOGGER.error("Unable to get context factory to determine ganglia server", e);
            }
        }

        return serverPort;
    }

    private static void sendToGanglia(InetAddress address, int port, String name, String value, String type,
            String units, int slope, int tmax, int dmax) {
        DatagramSocket socket = null;
        try {
            socket = new DatagramSocket();
            byte[] buf = write(name, value, type, units, slope, tmax, dmax);
            DatagramPacket p = new DatagramPacket(buf, buf.length, address, port);
            socket.send(p);
        } catch (IOException e) {
            LOGGER.debug("Unable to send data to Ganglia", e);
        } finally {
            if (socket != null) {
                socket.close();
            }
        }
    }

    private static byte[] write(String name, String value, String type, String units, int slope, int tmax,
            int dmax) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            DataOutputStream dos = new DataOutputStream(baos);
            dos.writeInt(0);
            writeXDRString(dos, type);
            writeXDRString(dos, name);
            writeXDRString(dos, value);
            writeXDRString(dos, units);
            dos.writeInt(slope);
            dos.writeInt(tmax);
            dos.writeInt(dmax);
            return baos.toByteArray();
        } catch (IOException e) {
            // really this is impossible
            return null;
        }
    }

    private static void writeXDRString(DataOutputStream dos, String s) throws IOException {
        dos.writeInt(s.length());
        dos.writeBytes(s);
        int offset = s.length() % 4;
        if (offset != 0) {
            for (int i = offset; i < 4; ++i) {
                dos.writeByte(0);
            }
        }
    }

}