// This file is part of OpenTSDB. // Copyright (C) 2014 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.tools; import java.util.ArrayList; import java.util.List; import net.opentsdb.core.TSDB; import net.opentsdb.core.Tags; import net.opentsdb.search.SearchQuery; import net.opentsdb.search.TimeSeriesLookup; import net.opentsdb.search.SearchQuery.SearchType; import net.opentsdb.utils.Config; import net.opentsdb.utils.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Handles searching from the command line. Enables lookups of time series * information given a metric, tagk, tagv or combination thereof */ final class Search { private static final Logger LOG = LoggerFactory.getLogger(Search.class); /** Prints usage. */ static void usage(final ArgP argp, final String errmsg) { System.err.println(errmsg); System.err.println("Usage: search <subcommand> args\n" + "Sub commands:\n" + " lookup <query>: Retreives a list of time series with the given\n" + " metric, tagk, tagv or any combination thereof.\n"); if (argp != null) { System.err.print(argp.usage()); } } /** * Entry point to run the search utility * @param args Command line arguments * @throws Exception If something goes wrong */ public static void main(String[] args) throws Exception { ArgP argp = new ArgP(); CliOptions.addCommon(argp); argp.addOption("--use-data-table", "Scan against the raw data table instead of the meta data table."); args = CliOptions.parse(argp, args); if (args == null) { usage(argp, "Invalid usage"); System.exit(2); } else if (args.length < 1) { usage(argp, "Not enough arguments"); System.exit(2); } final boolean use_data_table = argp.has("--use-data-table"); Config config = CliOptions.getConfig(argp); final TSDB tsdb = new TSDB(config); tsdb.checkNecessaryTablesExist().joinUninterruptibly(); int rc; try { rc = runCommand(tsdb, use_data_table, args); } finally { try { tsdb.getClient().shutdown().joinUninterruptibly(); LOG.info("Gracefully shutdown the TSD"); } catch (Exception e) { LOG.error("Unexpected exception while shutting down", e); rc = 42; } } System.exit(rc); } /** * Determines the command requested of the user can calls the appropriate * method. * @param tsdb The TSDB to use for communication * @param use_data_table Whether or not lookups should be done on the full * data table * @param args Arguments to parse * @return An exit code */ private static int runCommand(final TSDB tsdb, final boolean use_data_table, final String[] args) throws Exception { final int nargs = args.length; if (args[0].equals("lookup")) { if (nargs < 2) { // need a query usage(null, "Not enough arguments"); return 2; } return lookup(tsdb, use_data_table, args); } else { usage(null, "Unknown sub command: " + args[0]); return 2; } } /** * Performs a time series lookup given a query like "metric tagk=tagv" where * a list of all time series containing the given metric and tag pair will be * dumped to standard out. Tag pairs can be given with empty tagk or tagvs to * and the metric is option. E.g. a query of "=web01" will return all time * series with a tag value of "web01". * By default the lookup is performed against the tsdb-meta table. If the * "--use_data_table" flag is supplied, the main data table will be scanned. * @param tsdb The TSDB to use for communication * @param use_data_table Whether or not lookups should be done on the full * data table * @param args Arguments to parse * @return An exit code */ private static int lookup(final TSDB tsdb, final boolean use_data_table, final String[] args) throws Exception { if (!use_data_table) { tsdb.getClient().ensureTableExists( tsdb.getConfig().getString( "tsd.storage.hbase.meta_table")).joinUninterruptibly(); } final SearchQuery query = new SearchQuery(); query.setType(SearchType.LOOKUP); int index = 1; if (!args[index].contains("=")) { query.setMetric(args[index++]); } final List<Pair<String, String>> tags = new ArrayList<Pair<String, String>>(args.length - index); for (; index < args.length; index++) { Tags.parse(tags, args[index]); } query.setTags(tags); if (use_data_table) { query.setUseMeta(false); LOG.warn("NOTE: Scanning the full data table may take a long time"); } final TimeSeriesLookup lookup = new TimeSeriesLookup(tsdb, query); lookup.setToStdout(true); lookup.lookup(); return 0; } }