// 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.tsd; import java.io.IOException; import java.util.HashMap; import java.util.List; import org.jboss.netty.handler.codec.http.HttpMethod; import org.jboss.netty.handler.codec.http.HttpResponseStatus; import net.opentsdb.core.TSDB; import net.opentsdb.utils.JSON; /** * Handles the suggest endpoint that returns X number of metrics, tagks or * tagvs that start with the given string. It's used for auto-complete entries * and does not support wildcards. */ final class SuggestRpc implements HttpRpc { /** * Handles an HTTP based suggest query * <b>Note:</b> This method must remain backwards compatible with the 1.x * API call * @throws IOException if there is an error parsing the query or formatting * the output * @throws BadRequestException if the user supplied bad data */ public void execute(final TSDB tsdb, final HttpQuery query) throws IOException { // only accept GET/POST if (query.method() != HttpMethod.GET && query.method() != HttpMethod.POST) { throw new BadRequestException(HttpResponseStatus.METHOD_NOT_ALLOWED, "Method not allowed", "The HTTP method [" + query.method().getName() + "] is not permitted for this endpoint"); } final String type; final String q; final String max; if (query.apiVersion() > 0 && query.method() == HttpMethod.POST) { final HashMap<String, String> map = query.serializer().parseSuggestV1(); type = map.get("type"); if (type == null || type.isEmpty()) { throw new BadRequestException("Missing 'type' parameter"); } q = map.get("q") == null ? "" : map.get("q"); max = map.get("max"); } else { type = query.getRequiredQueryStringParam("type"); q = query.hasQueryStringParam("q") ? query.getQueryStringParam("q") : ""; max = query.getQueryStringParam("max"); } final int max_results; if (max != null && !max.isEmpty()) { try { max_results = Integer.parseInt(max); } catch (NumberFormatException nfe) { throw new BadRequestException("Unable to parse 'max' as a number"); } } else { max_results = 0; } List<String> suggestions; if ("metrics".equals(type)) { suggestions = max_results > 0 ? tsdb.suggestMetrics(q, max_results) : tsdb.suggestMetrics(q); } else if ("tagk".equals(type)) { suggestions = max_results > 0 ? tsdb.suggestTagNames(q, max_results) : tsdb.suggestTagNames(q); } else if ("tagv".equals(type)) { suggestions = max_results > 0 ? tsdb.suggestTagValues(q, max_results) : tsdb.suggestTagValues(q); } else { throw new BadRequestException("Invalid 'type' parameter:" + type); } if (query.apiVersion() > 0) { query.sendReply(query.serializer().formatSuggestV1(suggestions)); } else { // deprecated API query.sendReply(JSON.serializeToBytes(suggestions)); } } }