Java tutorial
/** * 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); } } } }