/*
* Copyright 2012 Nodeable Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.streamreduce.rest.resource.api;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.streamreduce.Constants;
import com.streamreduce.analytics.MetricCriteria;
import com.streamreduce.analytics.MetricName;
import com.streamreduce.core.dao.MetricDAO;
import com.streamreduce.rest.resource.AbstractResource;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
/**
* REST endpoints for getting access to metrics for reporting and external analysis.
*/
@Component
@Path("metrics")
public class MetricResource extends AbstractResource {
@Autowired
private MetricDAO metricDAO;
private static final Set<String> REQUIRED_PARAMS = ImmutableSet.of(
"ACCOUNT_ID",
"METRIC_NAME",
"GRANULARITY"
);
private static final Set<String> NUMERICAL_PARAMS = ImmutableSet.of(
"END_TIME",
"PAGE_NUM",
"PAGE_SIZE",
"START_TIME"
);
@GET
public Response getMetrics(@Context UriInfo context) {
MultivaluedMap<String, String> queryParams = context.getQueryParameters();
Map<String, List<String>> criteria = new HashMap<>();
String accountId;
String metricName;
String granularity;
Long startTime = null;
Long endTime = null;
int pageNum = 1; // Reasonable default
int pageSize = 1; // Reasonable default
// TODO: Check that the user is logged in and accessing metrics that are either global or in their account
// Ensure required query parameters are present, in some form
for (String queryParam : REQUIRED_PARAMS) {
if (!queryParams.containsKey(queryParam) || !StringUtils.hasText(queryParams.getFirst(queryParam))) {
return error(queryParam + " is a required, non-empty query parameter.",
Response.status(Response.Status.BAD_REQUEST));
}
}
accountId = queryParams.getFirst("ACCOUNT_ID");
metricName = queryParams.getFirst("METRIC_NAME");
granularity = queryParams.getFirst("GRANULARITY");
// Further validate the METRIC_NAME to ensure it's a valid metric name
try {
MetricName.valueOf(metricName);
} catch (IllegalArgumentException e) {
return error(metricName + " is not a valid METRIC_NAME.", Response.status(Response.Status.BAD_REQUEST));
}
// Further validate the GRANULARITY by checking the value is one of the canned values
if (!Constants.KNOWN_GRANULARITY_NAMES.keySet().contains(granularity)) {
return error(granularity + " is not a valid GRANULARITY.", Response.status(Response.Status.BAD_REQUEST));
}
// Gather/Validate numerical parameters
for (String queryParam : NUMERICAL_PARAMS) {
if (queryParams.containsKey(queryParam)) {
try {
Long.parseLong(queryParams.getFirst(queryParam));
} catch (NumberFormatException e) {
return error(queryParam + " parameter should be a number.",
Response.status(Response.Status.BAD_REQUEST));
}
}
}
if (queryParams.containsKey("START_TIME")) {
startTime = Long.parseLong(queryParams.getFirst("START_TIME"));
}
if (queryParams.containsKey("END_TIME")) {
endTime = Long.parseLong(queryParams.getFirst("END_TIME"));
}
if (queryParams.containsKey("PAGE_NUM")) {
pageNum = Integer.parseInt(queryParams.getFirst("PAGE_NUM"));
}
if (queryParams.containsKey("PAGE_SIZE")) {
pageSize = Integer.parseInt(queryParams.getFirst("PAGE_SIZE"));
}
// Gather/Validate criteria
for (String queryParam : queryParams.keySet()) {
if (queryParam.startsWith("criteria.")) {
String[] paramParts = queryParam.split("\\.");
if (paramParts.length != 2) {
return error("Your metric criteria is improperly structured, expected: " +
"criteria.YOUR_CRITERIA_NAME=YOUR_CRITERIA_VALUE.",
Response.status(Response.Status.BAD_REQUEST));
}
try {
MetricCriteria.valueOf(paramParts[1]);
} catch (IllegalArgumentException e) {
return error(paramParts[1] + " is not a valid METRIC_CRITERIA.",
Response.status(Response.Status.BAD_REQUEST));
}
criteria.put(paramParts[1], queryParams.get(queryParam));
}
}
return Response.ok(
JSONObject.fromObject(ImmutableMap.of(
"metrics", metricDAO.getMetrics(accountId, metricName, criteria,
Constants.KNOWN_GRANULARITY_NAMES.get(granularity),
startTime, endTime, pageNum, pageSize).toString())
)
).build();
}
}