OpenTSDB源码分析之TSDB表操作(查询)

来源:互联网 发布:网络棋牌游戏宣传语 编辑:程序博客网 时间:2024/05/17 10:29

TSDB表的行键比tsdb-uid表复杂,查询也要复杂一些,这种复杂性体现在字段过滤器,在该过滤器中监控指标、日期范围和标签都要考虑到。

       所有的过滤器都通过TsdbQuery.run()方法实现,创建带过滤器的扫描器,遍历返回的行和收集数据供显示使用,使用辅助方法TsdbQuery.getScanner()和TsdbQuery.findSpans()。

       Tsdb表的查询可以具体查看CliQuery.main()方法。

public static void main(String[] args) throws Exception {/** * 将查询结果打印输出 */// args = new String[] { "2013/09/08-12:57", "2013/10/20-16:57", "sum",// "t22", "host=foo"};/** * 查询输出写入到gnuplot加载文件中 w l lt 3 lw 2(with line linetype 3 linewidth 2)为plot绘图参数不可缺少 */args = new String[] { "--graph=e:/a", "2013/09/08-12:57", "2013/10/20-16:57", /*"+format x=\"%a %d %H:%M\"",*/ "sum", "t22", "host=foo", "w l lt 3 lw 2" };ArgP argp = new ArgP();CliOptions.addCommon(argp);CliOptions.addVerbose(argp);argp.addOption("--graph", "BASEPATH", "Output data points to a set of files for gnuplot." + "  The path of the output files will start with"+ " BASEPATH.");args = CliOptions.parse(argp, args);if (args == null) {usage(argp, "Invalid usage.", 1);} else if (args.length < 3) {usage(argp, "Not enough arguments.", 2);}// get a config objectConfig config = CliOptions.getConfig(argp);final TSDB tsdb = new TSDB(config);tsdb.checkNecessaryTablesExist().joinUninterruptibly();final String basepath = argp.get("--graph");argp = null;Plot plot = null;try {plot = doQuery(tsdb, args, basepath != null);} finally {try {tsdb.shutdown().joinUninterruptibly();} catch (Exception e) {LOG.error("Unexpected exception", e);System.exit(1);}}if (plot != null) {try {/** * 将Plot写gnuplot加载文件 修改图片样式可以在Plot中实现 */final int npoints = plot.dumpToFiles(basepath);LOG.info("Wrote " + npoints + " for Gnuplot");} catch (IOException e) {LOG.error("Failed to write the Gnuplot file under " + basepath, e);System.exit(1);}}}private static Plot doQuery(final TSDB tsdb, final String args[], final boolean want_plot) {final ArrayList<String> plotparams = new ArrayList<String>();final ArrayList<Query> queries = new ArrayList<Query>();final ArrayList<String> plotoptions = new ArrayList<String>();/** * 给queries赋值(TsdbQuery)  * 给plotparams、plotoptions初始化 *  * 生成gnuplot加载文件内容示例如下:set term png small size 1024,768set xdata timeset timefmt "%s"if (GPVAL_VERSION < 4.6) set xtics rotate; else set xtics rotate rightset output "e:/a.png"set xrange ["1378645020":"1382288220"]set gridset style data linespointsset key right boxset format x "%a %d %H:%M"plot  "e:/a_0.dat" using 1:2 title "t22{host=foo}" w l lt 3 lw 2plotparams用于传参数行set format x "%a %d %H:%M"plotoptions用于plot参数如:w l lt 3 lw 2 */parseCommandLineQuery(args, tsdb, queries, plotparams, plotoptions);if (queries.isEmpty()) {usage(null, "Not enough arguments, need at least one query.", 2);}final Plot plot = (want_plot ? new Plot(queries.get(0).getStartTime(), queries.get(0).getEndTime()) : null);if (want_plot) {plot.setParams(parsePlotParams(plotparams));}final int nqueries = queries.size();for (int i = 0; i < nqueries; i++) {// TO DO(tsuna): Optimization: run each query in// parallel.最好是并行执行每个查询final StringBuilder buf = want_plot ? null : new StringBuilder();/** * 查询都在queries.get(i).run()中完成 */for (final DataPoints datapoints : queries.get(i).run()) {/** * 以gnuplot的加载文件输出 */if (want_plot) {plot.add(datapoints, plotoptions.get(i));/** * 打印输出 */} else {final String metric = datapoints.metricName();final String tagz = datapoints.getTags().toString();for (final DataPoint datapoint : datapoints) {buf.append(metric).append(' ').append(datapoint.timestamp()).append(' ');if (datapoint.isInteger()) {buf.append(datapoint.longValue());} else {buf.append(String.format("%f", datapoint.doubleValue()));}buf.append(' ').append(tagz).append('\n');System.out.print(buf);buf.delete(0, buf.length());}}}}return plot;}static void parseCommandLineQuery(final String[] args, final TSDB tsdb, final ArrayList<Query> queries, final ArrayList<String> plotparams,final ArrayList<String> plotoptions) {/** * 第一个参数为start_ts */long start_ts = DateTime.parseDateTimeString(args[0], null);if (start_ts >= 0)start_ts /= 1000;long end_ts = -1;/** * 把满足条件的第二个参数设定为end_ts */if (args.length > 3) {// see if we can detect(发现) an end timetry {if (args[1].charAt(0) != '+'&& (args[1].indexOf(':') >= 0 || args[1].indexOf('/') >= 0 || args[1].indexOf('-') >= 0 || Long.parseLong(args[1]) > 0)) {end_ts = DateTime.parseDateTimeString(args[1], null);}} catch (NumberFormatException nfe) {// ignore it as it means the third parameter is likely the// aggregator}}// temp fixup to seconds from ms until the rest of TSDB supports ms// Note you can't append this to the DateTime.parseDateTimeString() call// as// it clobbers -1 resultsif (end_ts >= 0)end_ts /= 1000;/** * 获取plotparams */int i = end_ts < 0 ? 1 : 2;while (i < args.length && args[i].charAt(0) == '+') {if (plotparams != null) {plotparams.add(args[i]);}i++;}while (i < args.length) {final Aggregator agg = Aggregators.get(args[i++]);final boolean rate = args[i].equals("rate");RateOptions rate_options = new RateOptions(false, Long.MAX_VALUE, RateOptions.DEFAULT_RESET_VALUE);if (rate) {i++;long counterMax = Long.MAX_VALUE;long resetValue = RateOptions.DEFAULT_RESET_VALUE;if (args[i].startsWith("counter")) {String[] parts = Tags.splitString(args[i], ',');if (parts.length >= 2 && parts[1].length() > 0) {counterMax = Long.parseLong(parts[1]);}if (parts.length >= 3 && parts[2].length() > 0) {resetValue = Long.parseLong(parts[2]);}rate_options = new RateOptions(true, counterMax, resetValue);i++;}}final boolean downsample = args[i].equals("downsample");if (downsample) {i++;}final int interval = downsample ? Integer.parseInt(args[i++]) : 0;final Aggregator sampler = downsample ? Aggregators.get(args[i++]) : null;final String metric = args[i++];final HashMap<String, String> tags = new HashMap<String, String>();while (i < args.length && args[i].indexOf(' ', 1) < 0 && args[i].indexOf('=', 1) > 0) {Tags.parse(tags, args[i++]);}if (i < args.length && args[i].indexOf(' ', 1) > 0) {plotoptions.add(args[i++]);}final Query query = tsdb.newQuery();query.setStartTime(start_ts);if (end_ts > 0) {query.setEndTime(end_ts);}query.setTimeSeries(metric, tags, agg, rate, rate_options);if (downsample) {query.downsample(interval, sampler);}queries.add(query);}}