package org.rrd4j.demo;
import static org.rrd4j.ConsolFun.AVERAGE;
import java.awt.Color;
import java.io.IOException;
import org.rrd4j.DsType;
import org.rrd4j.core.FetchData;
import org.rrd4j.core.FetchRequest;
import org.rrd4j.core.RrdDb;
import org.rrd4j.core.RrdDef;
import org.rrd4j.core.Sample;
import org.rrd4j.core.Util;
import org.rrd4j.graph.RrdGraph;
import org.rrd4j.graph.RrdGraphDef;
/**
* This class implements the example from the RRD tutorial using RRD4j:
* http://oss.oetiker.ch/rrdtool/tut/rrdtutorial.en.html
*
* This source file may be freely redistributed under the same terms as RRD4j.
*
* @author Chris Lott
*/
public class RrdTutorial {
// Arbitrary start point: 7th of March, 1999 at noon in MET,
// expressed in seconds since the unix Epoch.
// I'm in a different timezone so this isn't right:
// Util.getTimestamp(1999, 3, 7) + 12 * 60 * 60;
static final long START = 920804400;
// End is 80 minutes later
static final long END = START + 80 * 60;
private static final String SPEED = "speed";
// For graphs
static final String FILE = SPEED;
static final int IMG_WIDTH = 500;
static final int IMG_HEIGHT = 300;
static final String FILE_FORMAT = "png";
private static final String MYSPEED = "myspeed";
private static final String IMG_SRC_S_WIDTH_D_HEIGHT_D = "<img src='%s' width='%d' height = '%d'>";
private static final String REALSPEED = "realspeed";
/**
* <p>
* To run the tutorial code, use the following command:
* </p>
*
* <pre>
* java -cp rrd4j-{version}.jar org.rrd4j.demo.RrdTutorial
* </pre>
*
* @param args not used
* @throws IOException for many failure case
*/
public static void main(String[] args) throws IOException {
System.setProperty("java.awt.headless","true");
println("== Starting tutorial code");
final String rrdPath = Util.getRrd4jDemoPath(FILE + ".rrd");
final String speedSource = SPEED;
// rrdtool create test.rrd \
// --start 920804400 \
// DS:speed:COUNTER:600:U:U \
// RRA:AVERAGE:0.5:1:24 \
// RRA:AVERAGE:0.5:6:10
println("== Creating RRD file " + rrdPath + " with initial time "
+ START);
// Expect new data every 300 seconds
RrdDef rrdDef = new RrdDef(rrdPath, START, 300);
rrdDef.setVersion(2);
// A counter for km: heartbeat is 600 sec; min val 0; no max val.
// Heartbeat: after no update for the interval, declare value UNKNOWN
rrdDef.addDatasource(speedSource, DsType.COUNTER, 600, 0, Double.NaN);
// Add archive using fn AVERAGE, known:unkown ratio of 0.5,
// use 1 data point, keep 24 rows. I.e., this archive keeps the latest
// value, it's not actually an average.
rrdDef.addArchive(AVERAGE, 0.5, 1, 24);
// Add archive using fn AVERAGE, known:unkown ratio of 0.5,
// use 6 data points, keep 10 rows. I.e., this keeps an average over
// a 30 minute interval, and 10 * 30 = 300 minutes (5hrs) are kept.
rrdDef.addArchive(AVERAGE, 0.5, 6, 10);
// Create and check the database
println(rrdDef.dump());
println("Estimated file size: " + rrdDef.getEstimatedSize());
try (RrdDb rrdDb = new RrdDb(rrdDef)){
println("== RRD file created.");
if (rrdDb.getRrdDef().equals(rrdDef)) {
println("Checking RRD file structure... OK");
} else {
println("Invalid RRD file created. This is a serious bug, bailing out");
return;
}
}
// Reopen and get ready to update
RrdDb rrdDb = new RrdDb(rrdPath);
Sample sample = rrdDb.createSample();
// Add these data points:
// 12:05 12345 km
// 12:10 12357 km
// 12:15 12363 km
// 12:20 12363 km
// 12:25 12363 km
// 12:30 12373 km
// 12:35 12383 km
// 12:40 12393 km
// 12:45 12399 km
// 12:50 12405 km
// 12:55 12411 km
// 13:00 12415 km
// 13:05 12420 km
// 13:10 12422 km
// 13:15 12423 km
final int[] odoData = { 12345, 12357, 12363, 12363, 12363, 12373,
12383, 12393, 12399, 12405, 12411, 12415, 12420, 12422, 12423 };
println("== Adding odometer data");
final int fiveMinutes = 5 * 60;
for (int i = 0; i < odoData.length; ++i) {
// First sample is 12:05, so use i + 1
sample.setTime(START + (i + 1) * fiveMinutes);
sample.setValue(speedSource, odoData[i]);
// Store the value
sample.update();
}
rrdDb.close();
println("== Finished. RRD file updated " + odoData.length + " times");
// test read-only access!
rrdDb = new RrdDb(rrdPath, true);
println("File reopen in read-only mode");
println("== Last update time was: " + rrdDb.getLastUpdateTime());
println("== Last info was: " + rrdDb.getInfo());
// rrdtool fetch test.rrd AVERAGE --start 920804400 --end 920809200
// Fetch data at finest resolution (300 sec), which is the default.
println("== Fetch request for the interval at default resolution:");
FetchRequest request = rrdDb.createFetchRequest(AVERAGE, START, END);
println(request.dump());
println("== Fetching data at default resolution");
FetchData fetchData = request.fetchData();
println("== Data fetched, " + fetchData.getRowCount()
+ " points obtained");
// This output is different from the tutorial output from rrdtool;
// it includes 920804400:nan but *not* 920809500:nan
println(fetchData.toString());
long coarseRes = 1800;
println("== Fetch request for the interval at coarse resolution:");
// START is before the first data point; END is after the last data
// point; ensure start and end are even multiples of the resolution
FetchRequest request2 = rrdDb.createFetchRequest(AVERAGE, START
/ coarseRes * coarseRes, END / coarseRes * coarseRes, 1800);
println(request2.dump());
println("== Fetching data at coarse resolution");
FetchData fetchData2 = request2.fetchData();
println("== Data fetched, " + fetchData2.getRowCount()
+ " points obtained");
println(fetchData2.toString());
// Done with direct access
rrdDb.close();
// Graph 1 has units in millis
// rrdtool graph speed.png \
// --start 920804400 --end 920808000 \
// DEF:myspeed=test.rrd:speed:AVERAGE \
// LINE2:myspeed#FF0000
println("== Creating graph 1");
RrdGraphDef gDef1 = new RrdGraphDef();
gDef1.setWidth(IMG_WIDTH);
gDef1.setHeight(IMG_HEIGHT);
String img1Path = Util.getRrd4jDemoPath(FILE + "." + FILE_FORMAT);
gDef1.setFilename(img1Path);
gDef1.setStartTime(920804400);
gDef1.setEndTime(920808000);
gDef1.datasource(MYSPEED, rrdPath, SPEED, AVERAGE);
gDef1.line(MYSPEED, new Color(0xFF, 0x00, 0x00), SPEED);
gDef1.comment("Graph 1\\r");
gDef1.setImageInfo(IMG_SRC_S_WIDTH_D_HEIGHT_D);
gDef1.setImageFormat(FILE_FORMAT);
println("Rendering graph 1");
RrdGraph graph1 = new RrdGraph(gDef1);
println(graph1.getRrdGraphInfo().dump());
println("== Graph 1 created");
// Graph 2 adjusts the units etc.
// rrdtool graph speed2.png \
// --start 920804400 --end 920808000 \
// --vertical-label m/s \
// DEF:myspeed=test.rrd:speed:AVERAGE \
// CDEF:realspeed=myspeed,1000,\* \
// LINE2:realspeed#FF0000
println("== Creating graph 2");
RrdGraphDef gDef2 = new RrdGraphDef();
gDef2.setWidth(IMG_WIDTH);
gDef2.setHeight(IMG_HEIGHT);
String img2Path = Util.getRrd4jDemoPath(FILE + "2" + "." + FILE_FORMAT);
gDef2.setFilename(img2Path);
gDef2.setStartTime(920804400);
gDef2.setEndTime(920808000);
gDef2.setVerticalLabel("m/s");
gDef2.datasource(MYSPEED, rrdPath, SPEED, AVERAGE);
gDef2.datasource(REALSPEED, "myspeed,1000,*");
gDef2.line(REALSPEED, new Color(0xFF, 0x00, 0x00), REALSPEED);
gDef2.comment("Graph 2\\r");
gDef2.setImageInfo(IMG_SRC_S_WIDTH_D_HEIGHT_D);
gDef2.setImageFormat(FILE_FORMAT);
println("Rendering graph 2");
RrdGraph graph2 = new RrdGraph(gDef2);
println(graph2.getRrdGraphInfo().dump());
println("== Graph 2 created");
// Graph 3 is fancier yet
// rrdtool graph speed3.png \
// --start 920804400 --end 920808000 \
// --vertical-label km/h \
// DEF:myspeed=test.rrd:speed:AVERAGE \
// "CDEF:kmh=myspeed,3600,*" \
// CDEF:fast=kmh,100,GT,kmh,0,IF \
// CDEF:good=kmh,100,GT,0,kmh,IF \
// HRULE:100#0000FF:"Maximum allowed" \
// AREA:good#00FF00:"Good speed" \
// AREA:fast#FF0000:"Too fast"
println("== Creating graph 3");
RrdGraphDef gDef3 = new RrdGraphDef();
gDef3.setWidth(IMG_WIDTH);
gDef3.setHeight(IMG_HEIGHT);
String img3Path = Util.getRrd4jDemoPath(FILE + "3" + "." + FILE_FORMAT);
gDef3.setFilename(img3Path);
gDef3.setStartTime(920804400);
gDef3.setEndTime(920808000);
gDef3.setVerticalLabel("km/h");
gDef3.datasource(MYSPEED, rrdPath, SPEED, AVERAGE);
gDef3.datasource("kmh", "myspeed,3600,*");
gDef3.datasource("fast", "kmh,100,GT,kmh,0,IF");
gDef3.datasource("good", "kmh,100,GT,0,kmh,IF");
gDef3.hrule(100, new Color(0x00, 0x00, 0xFF), "Maximum allowed");
gDef3.area("good", new Color(0x00, 0xFF, 0x00), "Good Speed");
gDef3.area("fast", new Color(0xFF, 0x00, 0x00), "Too fast");
gDef3.comment("Graph 3\\r");
gDef3.setImageInfo(IMG_SRC_S_WIDTH_D_HEIGHT_D);
gDef3.setImageFormat(FILE_FORMAT);
println("Rendering graph 3");
RrdGraph graph3 = new RrdGraph(gDef3);
println(graph3.getRrdGraphInfo().dump());
println("== Graph 3 created");
// Graph 4 is the fanciest
// rrdtool graph speed4.png \
// --start 920804400 --end 920808000 \
// --vertical-label km/h \
// DEF:myspeed=test.rrd:speed:AVERAGE \
// CDEF:nonans=myspeed,UN,0,myspeed,IF \
// CDEF:kmh=nonans,3600,* \
// CDEF:fast=kmh,100,GT,100,0,IF \
// CDEF:over=kmh,100,GT,kmh,100,-,0,IF \
// CDEF:good=kmh,100,GT,0,kmh,IF \
// HRULE:100#0000FF:"Maximum allowed" \
// AREA:good#00FF00:"Good speed" \
// AREA:fast#550000:"Too fast" \
// STACK:over#FF0000:"Over speed"
println("== Creating graph 4");
RrdGraphDef gDef4 = new RrdGraphDef();
gDef4.setWidth(IMG_WIDTH);
gDef4.setHeight(IMG_HEIGHT);
String img4Path = Util.getRrd4jDemoPath(FILE + "4" + "." + FILE_FORMAT);
gDef4.setFilename(img4Path);
gDef4.setStartTime(920804400);
gDef4.setEndTime(920808000);
gDef4.setVerticalLabel("km/h");
gDef4.datasource(MYSPEED, rrdPath, SPEED, AVERAGE);
gDef4.datasource("nonans", "myspeed,UN,0,myspeed,IF");
gDef4.datasource("kmh", "nonans,3600,*");
gDef4.datasource("fast", "kmh,100,GT,100,0,IF");
gDef4.datasource("over", "kmh,100,GT,kmh,100,-,0,IF");
gDef4.datasource("good", "kmh,100,GT,0,kmh,IF");
gDef4.hrule(100, new Color(0x00, 0x00, 0xFF), "Maximum allowed");
gDef4.area("good", new Color(0x00, 0xFF, 0x00), "Good Speed");
gDef4.area("fast", new Color(0x55, 00, 00), "Too fast");
gDef4.stack("over", new Color(0xff, 0x00, 0x00), "Over speed");
gDef4.comment("Graph 4\\r");
gDef4.setImageInfo(IMG_SRC_S_WIDTH_D_HEIGHT_D);
gDef4.setImageFormat(FILE_FORMAT);
println("Rendering graph 4");
RrdGraph graph4 = new RrdGraph(gDef4);
println(graph4.getRrdGraphInfo().dump());
println("== Graph 4 created");
}
static void println(String msg) {
System.out.println(msg);
}
static void print(String msg) {
System.out.print(msg);
}
}