ddf.metrics.reporting.internal.rrd4j.RrdDumper.java Source code

Java tutorial

Introduction

Here is the source code for ddf.metrics.reporting.internal.rrd4j.RrdDumper.java

Source

/**
 * Copyright (c) Codice Foundation
 * 
 * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
 * General Public License as published by the Free Software Foundation, either version 3 of the
 * License, or any later version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details. A copy of the GNU Lesser General Public License
 * is distributed along with this program and can be found at
 * <http://www.gnu.org/licenses/lgpl.html>.
 * 
 **/
package ddf.metrics.reporting.internal.rrd4j;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.rrd4j.ConsolFun;
import org.rrd4j.DsType;
import org.rrd4j.core.FetchData;
import org.rrd4j.core.FetchRequest;
import org.rrd4j.core.RrdDb;
import org.rrd4j.graph.RrdGraph;
import org.rrd4j.graph.RrdGraphDef;

import ddf.metrics.reporting.internal.MetricsGraphException;

public class RrdDumper {

    private static final String months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
            "Nov", "Dec" };

    private static final double METRICS_MAX_THRESHOLD = 4000000000.0;

    public static void main(String[] args) throws Exception {

        // String rrdFilename = args[0];
        String[] rrdFilenames = new String[] { "C:/DDF/jvmUptime.rrd" };

        for (String rrdFilename : rrdFilenames) {
            RrdDb rrdDb = new RrdDb(rrdFilename, true);
            long endTime = System.currentTimeMillis() / 1000;
            long duration = TimeUnit.SECONDS.convert(24L, TimeUnit.DAYS);
            long startTime = endTime - duration;
            //
            // Calendar cal = Calendar.getInstance();
            // cal.set(2013, 7, 21, 15, 40);
            // long startTime = cal.getTimeInMillis()/1000;
            // cal.set(2013, 7, 22, 8, 0);
            // long endTime = cal.getTimeInMillis()/1000;

            System.out.println(
                    "\n\n>>>>>>>>>>>>>>>>>>>  RRD File:  " + rrdFilename + "  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n\n");
            dumpData(ConsolFun.TOTAL, "TOTAL", rrdDb, "COUNTER", startTime, endTime);

            displayGraph("Metric Name", rrdFilename, startTime, endTime, "Y-Axis Label", "Graph Title");
        }
    }

    private static void dumpData(ConsolFun consolFun, String dataType, RrdDb rrdDb, String dsType, long startTime,
            long endTime) throws Exception {
        FetchRequest fetchRequest = rrdDb.createFetchRequest(consolFun, startTime, endTime);
        FetchData fetchData = fetchRequest.fetchData();
        System.out.println("************  " + dsType + ": " + dataType + "  **************");
        // System.out.println(fetchData.dump());

        int rrdStep = 60; // in seconds
        long[] timestamps = fetchData.getTimestamps();
        double[] values = fetchData.getValues(0);
        double[] adjustedValues = new double[values.length];
        for (int i = 0; i < values.length; i++) {
            double adjustedValue = values[i] * rrdStep;
            adjustedValues[i] = adjustedValue;

            System.out.println(getCalendarTime(timestamps[i]) + ":  " + values[i] + "   (adjusted value = "
                    + adjustedValue + ",   floor = " + Math.floor(adjustedValue) + ",   round = "
                    + Math.round(adjustedValue) + ")");
        }

        System.out.println("adjustedValues.length = " + adjustedValues.length);

        for (int i = 0; i < adjustedValues.length; i++) {
            // System.out.println("adjustedValue[" + i + "] = " + adjustedValues[i]);
            if (adjustedValues[i] > METRICS_MAX_THRESHOLD) {
                System.out.println("Value [" + adjustedValues[i] + "] is an OUTLIER");
            }
        }

        System.out.println("*******  RRDB dump  **********");
        System.out.println(rrdDb.dump());
    }

    private static String getCalendarTime(long timestamp) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp * 1000);

        String calTime = months[calendar.get(Calendar.MONTH)] + " " + calendar.get(Calendar.DATE) + " "
                + calendar.get(Calendar.YEAR) + " ";

        calTime += addLeadingZero(calendar.get(Calendar.HOUR_OF_DAY)) + ":";
        calTime += addLeadingZero(calendar.get(Calendar.MINUTE)) + ":";
        calTime += addLeadingZero(calendar.get(Calendar.SECOND));

        return calTime;
    }

    private static String addLeadingZero(int value) {
        if (value < 10) {
            return "0" + String.valueOf(value);
        }

        return String.valueOf(value);
    }

    public static void displayGraph(String metricName, String rrdFilename, long startTime, long endTime,
            String verticalAxisLabel, String title) throws IOException, MetricsGraphException {
        // Create RRD DB in read-only mode for the specified RRD file
        RrdDb rrdDb = new RrdDb(rrdFilename, true);

        // Extract the data source (should always only be one data source per RRD file - otherwise
        // we have a problem)
        if (rrdDb.getDsCount() != 1) {
            throw new MetricsGraphException("Only one data source per RRD file is supported - RRD file "
                    + rrdFilename + " has " + rrdDb.getDsCount() + " data sources.");
        }

        // Define attributes of the graph to be created for this metric
        RrdGraphDef graphDef = new RrdGraphDef();
        graphDef.setTimeSpan(startTime, endTime);
        graphDef.setImageFormat("PNG");
        graphDef.setShowSignature(false);
        graphDef.setStep(60);
        graphDef.setVerticalLabel(verticalAxisLabel);
        graphDef.setHeight(500);
        graphDef.setWidth(1000);
        graphDef.setTitle(title);

        DsType dataSourceType = rrdDb.getDatasource(0).getType();

        // Determine if the Data Source for this RRD file is a COUNTER or GAUGE
        // (Need to know this because COUNTER data is averaged across samples and the vertical axis
        // of the
        // generated graph by default will show data per rrdStep interval)
        if (dataSourceType == DsType.DERIVE) {
            long rrdStep = rrdDb.getRrdDef().getStep();

            // Multiplied by the rrdStep to "undo" the automatic averaging that RRD does
            // when it collects TOTAL data - we want the actual totals for the step, not
            // the average of the totals.
            graphDef.datasource("myTotal", rrdFilename, "data", ConsolFun.TOTAL);
            graphDef.datasource("realTotal", "myTotal," + rrdStep + ",*");
            graphDef.datasource("validTotal", "realTotal," + METRICS_MAX_THRESHOLD + ",GT,UNKN,realTotal,IF");
            graphDef.line("validTotal", Color.BLUE, convertCamelCase(metricName), 2);

            // Add some spacing between the graph and the summary stats shown beneath the graph
            graphDef.comment("\\s");
            graphDef.comment("\\s");
            graphDef.comment("\\c");

            // Average, Min, and Max over all of the TOTAL data - displayed at bottom of the graph
            graphDef.gprint("validTotal", ConsolFun.AVERAGE, "Average = %.3f%s");
            graphDef.gprint("validTotal", ConsolFun.MIN, "Min = %.3f%s");
            graphDef.gprint("validTotal", ConsolFun.MAX, "Max = %.3f%s");
        } else if (dataSourceType == DsType.GAUGE) {
            graphDef.datasource("myAverage", rrdFilename, "data", ConsolFun.AVERAGE);
            graphDef.line("myAverage", Color.RED, convertCamelCase(metricName), 2);

            // Add some spacing between the graph and the summary stats shown beneath the graph
            graphDef.comment("\\s");
            graphDef.comment("\\s");
            graphDef.comment("\\c");

            // Average, Min, and Max over all of the AVERAGE data - displayed at bottom of the graph
            graphDef.gprint("myAverage", ConsolFun.AVERAGE, "Average = %.3f%s");
            graphDef.gprint("myAverage", ConsolFun.MIN, "Min = %.3f%s");
            graphDef.gprint("myAverage", ConsolFun.MAX, "Max = %.3f%s");
        } else {
            rrdDb.close();
            throw new MetricsGraphException("Unsupported data source type " + dataSourceType.name()
                    + " in RRD file " + rrdFilename + ", only COUNTER and GAUGE data source types supported.");
        }

        rrdDb.close();

        // Use "-" as filename so that RRD creates the graph only in memory (no file is
        // created, hence no file locking problems due to race conditions between multiple clients)
        graphDef.setFilename("graph.gif");
        RrdGraph graph = new RrdGraph(graphDef);
        BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
        graph.render(bi.getGraphics());
    }

    public static String convertCamelCase(String input) {
        String[] parts = StringUtils.splitByCharacterTypeCamelCase(input);
        String convertedStr = StringUtils.join(parts, " ");
        convertedStr = WordUtils.capitalizeFully(convertedStr).trim();

        return convertedStr;
    }
}