Package

Source Code of gmetric3


/*
* This is the MIT License
* http://www.opensource.org/licenses/mit-license.php
*
* Copyright (c) 2009 Nick Galbreath
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/

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

/**
*
* This supports the 'ganglia 3' gmetric format.  It isn't backwards
* compatible.
*
* Note this isn't very java-like.  You might want to add a wrapper
*
* Note: thread safe, there is no state or use of static objects
*
* Note: "extra" data in the metadata package is not supported.  It's pretty
*  easy to add if desired.  See code below
*
* Note: we could create multiple "write" versoins to do binary
*  encoding of integers and doubles instead of converting them to
*  strings
*
* NOTE: The send functions send both a metadata packet and a value
* packet.  In the future it would be nice to seprate out the two, so
* you can send the metadata packet infrequently.
*
*/
class gmetric3 {

    public final static int SLOPE_ZERO         = 0;
    public final static int SLOPE_POSITIVE     = 1;
    public final static int SLOPE_NEGATIVE     = 2;
    public final static int SLOPE_BOTH         = 3;
    public final static int SLOPE_UNSPECIFIED  = 4;

    public final static String VALUE_STRING          = "string";
    public final static String VALUE_UNSIGNED_SHORT  = "uint16";
    public final static String VALUE_SHORT           = "int16";
    public final static String VALUE_UNSIGNED_INT    = "uint32";
    public final static String VALUE_INT             = "int32";
    public final static String VALUE_FLOAT           = "float";
    public final static String VALUE_DOUBLE          = "double";
    public final static String VALUE_TIMESTAMP       = "timestamp";

    public static void send(InetAddress address, int port,
          String host,
          String name, String value, String type,
          String units, int slope, int tmax, int dmax)
    {
  try {
      DatagramSocket socket = new DatagramSocket();
      byte[] buf = writemeta(host, name, type, units, slope, tmax, dmax);
      DatagramPacket p = new DatagramPacket(buf, buf.length,
              address, port);
      socket.send(p);
      buf = writevalue(host, name, value);
      p = new DatagramPacket(buf, buf.length, address, port);
      socket.send(p);
  } catch (IOException e) {
      // who cares
  }
    }

    public static void send(InetAddress address, int port,
          String host,
          String name, double dvalue, String type,
          String units, int slope, int tmax, int dmax)
    {
  String value = Double.toString(dvalue);
  send(address, port, host, name, value, type, units, slope, tmax, dmax);
    }

    public static void send(InetAddress address, int port,
          String host,
          String name, int dvalue, String type,
          String units, int slope, int tmax, int dmax)
    {
  String value = Integer.toString(dvalue);
  send(address, port, host, name, value, type, units, slope, tmax, dmax);
    }

    /*
     * EVERYTHING BELOW HERE YOU DON"T NEED TO USE
     */

    public static byte[] writevalue(String host, String name, String val)
    {
  try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      DataOutputStream dos = new DataOutputStream(baos);
      dos.writeInt(128+5)// string
      writeXDRString(dos, host);
      writeXDRString(dos, name);
      dos.writeInt(0);
      writeXDRString(dos, "%s");
      writeXDRString(dos, val);
      return baos.toByteArray();
  } catch (IOException e) {
      // really this is impossible
      return null;
  }
    }

    public static byte[] writemeta(String host, String name, String type,
           String units, int slope, int tmax, int dmax)
    {
  try {
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      DataOutputStream dos = new DataOutputStream(baos);
      dos.writeInt(128)// gmetadata_full
      writeXDRString(dos, host);
      writeXDRString(dos, name);
      dos.writeInt(0);

      writeXDRString(dos, type);
      writeXDRString(dos, name);
      writeXDRString(dos, units);
      dos.writeInt(slope);
      dos.writeInt(tmax);
      dos.writeInt(dmax);
      dos.writeInt(0);

      // to add extra metadata it's something like this
      // assuming extradata is hashmap , then:
      //
      // write extradata.size();
      // foreach key,value in "extradata"
      //   writeXDRString(dos, key)
      //   writeXDRString(dos, value)


      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);
      }
  }
  /*
  bytes[] b = s.getBytes("utf8");
  int len = b.length();
  dos.writeInt(len);
  dos.write(b, 0, len);
  */
    }

    /*
     * Everything below here is just for testing
     */
    private static final byte[] HEXCHARS = {
  (byte)'0', (byte)'1', (byte)'2', (byte)'3',
  (byte)'4', (byte)'5', (byte)'6', (byte)'7',
  (byte)'8', (byte)'9', (byte)'a', (byte)'b',
  (byte)'c', (byte)'d', (byte)'e', (byte)'f'
    };

    private static String bytes2hex(byte[] raw)
    {
  try {
      int pos = 0;
      byte[] hex = new byte[2 * raw.length];
      for (int i = 0; i < raw.length; ++i) {
    int v = raw[i] & 0xFF;
    hex[pos++] = HEXCHARS[v >>> 4];
    hex[pos++] = HEXCHARS[v & 0xF];
      }

      return new String(hex, "ASCII");
  } catch (UnsupportedEncodingException e) {
      // impossible
      return "";
  }
    }

    /*
    public static void selfTest()
    {
  String expected = "0000000000000006737472696e67000000000003666f6f00000000036261720000000000000000030000003c00000000";
  byte[] data = write("foo", "bar", VALUE_STRING, "", SLOPE_BOTH, 60, 0);
  String result = bytes2hex(data);
  if (!expected.equals(result)) {
      System.out.println(expected);
      System.out.println(result);
      throw new RuntimeException("bad");
  }
    }
    */

    public static void main(String args[]) throws Exception {
  InetAddress remote = InetAddress.getByName("172.16.70.128");
  // System.out.println(remote);
  int port = 8649;
  String local = InetAddress.getLocalHost().getHostName();
  // System.out.println(local);

  gmetric3.send(remote, port, local, "craplog", "foobar", "string",
          "", gmetric.SLOPE_UNSPECIFIED, 100, 100);
  gmetric3.send(remote, port, local, "timedbreq", 9.99, "double",
          "req/sec", gmetric.SLOPE_BOTH, 100, 100);
    }
}
TOP

Related Classes of gmetric3

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.