// This file is part of OpenTSDB.
// Copyright (C) 2013 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.search;
import java.util.Collections;
import java.util.List;
import net.opentsdb.utils.Pair;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
/**
* Class used for passing and executing simple queries against with the search
* plugin. This may not be able to take advantage of all of the search engine's
* features but is intended to satisfy most common search requests.
* With 2.1 it now allows for time series lookup queries, using the meta or full
* data tables to determine what time series exist for a given metric, tag name,
* tag value or combination thereof.
* @since 2.0
*/
@JsonAutoDetect(fieldVisibility = Visibility.PUBLIC_ONLY)
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SearchQuery {
/**
* Types of searches to execute, chooses the different indexes and/or alters
* the output format
*/
public enum SearchType {
TSMETA,
TSMETA_SUMMARY,
TSUIDS,
UIDMETA,
ANNOTATION,
LOOKUP
}
/** The type of search to execute */
private SearchType type;
/** The actual query to execute */
private String query;
/** The metric to iterate over, may be null */
private String metric;
/** Optional tags to match on, may be null */
private List<Pair<String, String>> tags;
/** Whether or not to use the tsdb-meta table for lookups. Defaults to true */
private boolean use_meta;
/** Limit the number of responses so we don't overload the TSD or client */
private int limit;
/** Used for paging through a result set */
private int start_index;
/** Total results from the user */
private int total_results;
/** Ammount of time it took to complete the query (including parsing the
* response within the TSD
*/
private float time;
/** Results from the search engine. Object depends on the query type */
private List<Object> results;
/**
* Default ctor. Only sets use_meta to true. Other fields are left null.
*/
public SearchQuery() {
metric = "*";
use_meta = true;
limit = 25;
}
/**
* Overload to set the metric on creation
* @param metric The metric to filter on
*/
public SearchQuery(final String metric) {
this.metric = metric;
use_meta = true;
limit = 25;
}
/**
* Overload to set just the tags
* @param tags List of tagk/tagv pairs, either of which may be null
*/
public SearchQuery(final List<Pair<String, String>> tags) {
this.tags = tags;
metric = "*";
use_meta = true;
limit = 25;
}
/**
* Overload to set both metric and tags
* @param metric The metric to filter on
* @param tags List of tagk/tagv pairs, either of which may be null
*/
public SearchQuery(final String metric,
final List<Pair<String, String>> tags) {
this.metric = metric;
this.tags = tags;
use_meta = true;
limit = 25;
}
@Override
public String toString() {
final StringBuilder buf = new StringBuilder();
buf.append("type=").append(type).append(", query=")
.append(query).append(", metric=").append(metric)
.append(", tags=[");
if (tags != null) {
for(int i = 0; i < tags.size(); i++) {
if (i > 0) {
buf.append(", ");
}
buf.append("{").append(tags.get(i).getKey()).append("=")
.append(tags.get(i).getValue()).append("}");
}
}
buf.append("], use_meta=").append(use_meta)
.append(", limit=").append(limit).append(", start_index=")
.append(start_index);
return buf.toString();
}
/**
* Converts the human readable string to the proper enum
* @param type The string to parse
* @return The parsed enum
* @throws IllegalArgumentException if the type is missing or wsa not
* recognized
*/
public static SearchType parseSearchType(final String type) {
if (type == null || type.isEmpty()) {
throw new IllegalArgumentException("Type provided was null or empty");
}
if (type.toLowerCase().equals("tsmeta")) {
return SearchType.TSMETA;
} else if (type.toLowerCase().equals("tsmeta_summary")) {
return SearchType.TSMETA_SUMMARY;
} else if (type.toLowerCase().equals("tsuids")) {
return SearchType.TSUIDS;
} else if (type.toLowerCase().equals("uidmeta")) {
return SearchType.UIDMETA;
} else if (type.toLowerCase().equals("annotation")) {
return SearchType.ANNOTATION;
} else if (type.toLowerCase().equals("lookup")) {
return SearchType.LOOKUP;
} else {
throw new IllegalArgumentException("Unknown type: " + type);
}
}
// GETTERS AND SETTERS --------------------------
/** @return The type of query executed */
public SearchType getType() {
return type;
}
/** @return The query itself */
public String getQuery() {
return query;
}
/** @return Name of a metric to use for filtering */
public String getMetric() {
return metric;
}
/** @return List of tagk/tagv pairs, either of which may be null */
public List<Pair<String, String>> getTags() {
return tags;
}
/** @return Whether or not the lookup should be done on the main data table */
public boolean useMeta() {
return use_meta;
}
/** @return A limit on the number of results returned per query */
public int getLimit() {
return limit;
}
/** @return The starting index for paging through results */
public int getStartIndex() {
return start_index;
}
/** @return The total results matched on the query */
public int getTotalResults() {
return total_results;
}
/** @return The amount of time it took to complete the query */
public float getTime() {
return time;
}
/** @return The array of results. May be an empty list */
public List<Object> getResults() {
if (results == null) {
return Collections.emptyList();
}
return results;
}
/** @param type The type of query to execute */
public void setType(SearchType type) {
this.type = type;
}
/** @param query The query to execute */
public void setQuery(String query) {
this.query = query;
}
/** @param metric A metric to use for lookup filtering */
public void setMetric(String metric) {
this.metric = metric;
}
/** @param tags A list of tagk, tagv pairs, either of which may be null */
public void setTags(List<Pair<String, String>> tags) {
this.tags = tags;
}
/** @param use_meta Whether or not to use the data or meta table for lookups */
public void setUseMeta(boolean use_meta) {
this.use_meta = use_meta;
}
/** @param limit A limit to the number of results to return */
public void setLimit(int limit) {
this.limit = limit;
}
/** @param start_index Used for paging through a result set, starts at 0 */
public void setStartIndex(int start_index) {
this.start_index = start_index;
}
/** @param total_results The total number of results matched on the query */
public void setTotalResults(int total_results) {
this.total_results = total_results;
}
/** @param time The amount of time it took to complete the query */
public void setTime(float time) {
this.time = time;
}
/** @param results The result set*/
public void setResults(List<Object> results) {
this.results = results;
}
}