Skip to content

Commit

Permalink
Add example classes for queries and writing data.
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Larsen <clarsen@yahoo-inc.com>
  • Loading branch information
bryan4887 authored and manolama committed Dec 21, 2016
1 parent 8721acd commit 039bc41
Show file tree
Hide file tree
Showing 2 changed files with 340 additions and 0 deletions.
174 changes: 174 additions & 0 deletions src/examples/AddDataExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// This file is part of OpenTSDB.
// Copyright (C) 2015 The OpenTSDB Authors.
//
// This program 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 2.1 of the License, or (at your
// option) 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. You should have received a copy
// of the GNU Lesser General Public License along with this program. If not,
// see <http://www.gnu.org/licenses/>.

package net.opentsdb.examples;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import com.stumbleupon.async.Callback;
import com.stumbleupon.async.Deferred;

import net.opentsdb.core.TSDB;
import net.opentsdb.uid.NoSuchUniqueName;
import net.opentsdb.uid.UniqueId.UniqueIdType;
import net.opentsdb.utils.Config;

/**
* Examples for how to add points to the tsdb.
*
*/
public class AddDataExample {
private static String pathToConfigFile;

public static void processArgs(String[] args) {
// Set these as arguments so you don't have to keep path information in
// source files
if (args == null) {
System.err.println("First (and only) argument must be the full path to the opentsdb.conf file. (e.g. /User/thisUser/opentsdb/src/opentsdb.conf");
} else {
pathToConfigFile = args[0];
}
}

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



processArgs(args);

// Create a config object with a path to the file for parsing. Or manually
// override settings.
// e.g. config.overrideConfig("tsd.storage.hbase.zk_quorum", "localhost");
Config config = new Config(pathToConfigFile);
final TSDB tsdb = new TSDB(config);

// Declare new metric
String metricName = "dummyFromjavaAPI";
// First check to see it doesn't already exist
byte[] byteMetricUID; // we don't actually need this for the first
// .addPoint() call below.
// TODO: Ideally we could just call a not-yet-implemented tsdb.uIdExists()
// function.
// Note, however, that this is optional. If autometric is enabled, the UID will be assigned in call to addPoint().
try {
byteMetricUID = tsdb.getUID(UniqueIdType.METRIC, metricName);
} catch (IllegalArgumentException iae) {
System.out.println("Metric name not valid.");
iae.printStackTrace();
System.exit(1);
} catch (NoSuchUniqueName nsune) {
// If not, great. Create it.
byteMetricUID = tsdb.assignUid("metric", metricName);
}

// Make a single datum
long timestamp = System.currentTimeMillis();
long value = 314159;
// Make key-val
Map<String, String> tags = new HashMap<String, String>(1);
tags.put("dummy-key", "dummy-val1");




// Start timer
long startTime1 = System.currentTimeMillis();

int n = 100;
ArrayList<Deferred<Object>> deferreds = new ArrayList<Deferred<Object>>(n);
for (int i = 0; i < n; i++) {
Deferred<Object> deferred = tsdb.addPoint(metricName, timestamp, value + i, tags);
deferreds.add(deferred);

}

// Add the callbacks to the deferred object. (They might have already
// returned, btw)
// This will cause the calling thread to wait until the add has completed.

System.out.println("Waiting for deferred result to return...");
Deferred.groupInOrder(deferreds)
.addErrback(new AddDataExample().new errBack())
.addCallback(new AddDataExample().new succBack())
.join();

// Block the thread until the deferred returns it's result.
// deferred.join();

// End timer.
long elapsedTime1 = System.currentTimeMillis() - startTime1;
System.out.println("\nAdding " + n + " points took: " + elapsedTime1
+ " milliseconds.\n");


// Gracefully shutdown connection to TSDB
tsdb.shutdown();


}

// This is an optional errorback to handle when there is a failure.
class errBack implements Callback<String, Exception> {
public String call(final Exception e) throws Exception {
String message = ">>>>>>>>>>>Failure!>>>>>>>>>>>";
System.err.println(message);
return message;
}
};

// This is an optional success callback to handle when there is a success.
class succBack implements Callback<Object, ArrayList<Object>> {
public Object call(ArrayList<Object> results) {
for (Object res : results) {
if (res != null) {
if (res.toString().equals("MultiActionSuccess")) {
System.err.println(">>>>>>>>>>>Success!>>>>>>>>>>>");
}
} else {
System.err.println(">>>>>>>>>>>" + res.getClass() + ">>>>>>>>>>>");
}
}
return null;
}
};

public static long[] makeRandomValues(int num, Random rand) {
long[] values = new long[num];
for (int i = 0; i < num; i++) {
// define datum
values[i] = rand.nextInt();
}
return values;
}

public static long[] makeTimestamps(int num, Random rand) {

long[] timestamps = new long[num];
for (int i = 0; i < num; i++) {
// ensures that we won't try to put two data points in the same
// millisecond
try {
Thread.sleep(1); // in millis
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
// define datum
timestamps[i] = System.currentTimeMillis();
}
return timestamps;
}

}
166 changes: 166 additions & 0 deletions src/examples/QueryExample.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// This file is part of OpenTSDB.
// Copyright (C) 2010-2012 The OpenTSDB Authors.
//
// This program 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 2.1 of the License, or (at your
// option) 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. You should have received a copy
// of the GNU Lesser General Public License along with this program. If not,
// see <http://www.gnu.org/licenses/>.
package net.opentsdb.examples;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import com.stumbleupon.async.Callback;
import com.stumbleupon.async.Deferred;

import net.opentsdb.core.DataPoint;
import net.opentsdb.core.DataPoints;
import net.opentsdb.core.Query;
import net.opentsdb.core.SeekableView;
import net.opentsdb.core.TSDB;
import net.opentsdb.core.TSQuery;
import net.opentsdb.core.TSSubQuery;
import net.opentsdb.utils.Config;

/**
* One example on how to query.
* Taken from <a href="https://groups.google.com/forum/#!searchin/opentsdb/java$20api/opentsdb/6MKs-FkSLoA/gifHF327CIAJ">this thread</a>
* The metric and key query arguments assume that you've input data from the Quick Start tutorial
* <a href="http://opentsdb.net/docs/build/html/user_guide/quickstart.html">here.</a>
*/
public class QueryExample {

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

// Set these as arguments so you don't have to keep path information in
// source files
String pathToConfigFile = args[0]; // e.g. "/User/thisUser/opentsdb/src/opentsdb.conf"
String hostValue = args[1]; // e.g. "myComputerName"

// Create a config object with a path to the file for parsing. Or manually
// override settings.
// e.g. config.overrideConfig("tsd.storage.hbase.zk_quorum", "localhost");
Config config;
config = new Config(pathToConfigFile);
final TSDB tsdb = new TSDB(config);

// main query
final TSQuery query = new TSQuery();
// use any string format from
// http://opentsdb.net/docs/build/html/user_guide/query/dates.html
query.setStart("1h-ago");
// Optional: set other global query params

// at least one sub query required. This is where you specify the metric and
// tags
final TSSubQuery subQuery = new TSSubQuery();
subQuery.setMetric("proc.loadavg.1m");

// tags are optional but you can create and populate a map
final HashMap<String, String> tags = new HashMap<String, String>(1);
tags.put("host", hostValue);
subQuery.setTags(tags);

// you do have to set an aggregator. Just provide the name as a string
subQuery.setAggregator("sum");

// IMPORTANT: don't forget to add the subQuery
final ArrayList<TSSubQuery> subQueries = new ArrayList<TSSubQuery>(1);
subQueries.add(subQuery);
query.setQueries(subQueries);
query.setMsResolution(true); // otherwise we aggregate on the second.

// make sure the query is valid. This will throw exceptions if something
// is missing
query.validateAndSetQuery();

// compile the queries into TsdbQuery objects behind the scenes
Query[] tsdbqueries = query.buildQueries(tsdb);

// create some arrays for storing the results and the async calls
final int nqueries = tsdbqueries.length;
final ArrayList<DataPoints[]> results = new ArrayList<DataPoints[]>(
nqueries);
final ArrayList<Deferred<DataPoints[]>> deferreds = new ArrayList<Deferred<DataPoints[]>>(
nqueries);

// this executes each of the sub queries asynchronously and puts the
// deferred in an array so we can wait for them to complete.
for (int i = 0; i < nqueries; i++) {
deferreds.add(tsdbqueries[i].runAsync());
}

// Start timer
long startTime = System.nanoTime();

// This is a required callback class to store the results after each
// query has finished
class QueriesCB implements Callback<Object, ArrayList<DataPoints[]>> {
public Object call(final ArrayList<DataPoints[]> queryResults)
throws Exception {
results.addAll(queryResults);
return null;
}
}

// this will cause the calling thread to wait until ALL of the queries
// have completed.
try {
Deferred.groupInOrder(deferreds).addCallback(new QueriesCB())
.joinUninterruptibly();
} catch (Exception e) {
e.printStackTrace();
}

// End timer.
long elapsedTime = (System.nanoTime() - startTime) / (1000*1000);
System.out.println("Query returned in: " + elapsedTime + " milliseconds.");

// now all of the results are in so we just iterate over each set of
// results and do any processing necessary.
for (final DataPoints[] dataSets : results) {
for (final DataPoints data : dataSets) {
System.out.print(data.metricName());
Map<String, String> resolvedTags = data.getTags();
for (final Map.Entry<String, String> pair : resolvedTags.entrySet()) {
System.out.print(" " + pair.getKey() + "=" + pair.getValue());
}
System.out.print("\n");

final SeekableView it = data.iterator();
/*
* An important point about SeekableView:
* Because no data is copied during iteration and no new object gets
* created, the DataPoint returned must not be stored and gets
* invalidated as soon as next is called on the iterator (actually it
* doesn't get invalidated but rather its contents changes). If you want
* to store individual data points, you need to copy the timestamp and
* value out of each DataPoint into your own data structures.
*
* In the vast majority of cases, the iterator will be used to go once
* through all the data points, which is why it's not a problem if the
* iterator acts just as a transient "view". Iterating will be very
* cheap since no memory allocation is required (except to instantiate
* the actual iterator at the beginning).
*/
while (it.hasNext()) {
final DataPoint dp = it.next();
System.out.println(" " + dp.timestamp() + " "
+ (dp.isInteger() ? dp.longValue() : dp.doubleValue()));
}
System.out.println("");

// Gracefully shutdown connection to TSDB
tsdb.shutdown();
}
}
}

}

0 comments on commit 039bc41

Please sign in to comment.