/*
* Copyright © 2014 Cask Data, 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 co.cask.cdap.gateway.handlers.hooks;
import co.cask.cdap.common.conf.Constants;
import co.cask.cdap.gateway.GatewayFastTestsSuite;
import co.cask.cdap.gateway.GatewayTestBase;
import com.google.common.base.Charsets;
import com.google.common.io.ByteStreams;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.TimeUnit;
/**
* Test MetricReporterHook.
*/
public class MetricsReporterHookTestRun extends GatewayTestBase {
private static final String API_KEY = "SampleTestApiKey";
private static final Header AUTH_HEADER = new BasicHeader(Constants.Gateway.API_KEY, API_KEY);
@Test
public void testMetricsSuccess() throws Exception {
String context = "tag=namespace:system&tag=component:appfabric&tag=handler:PingHandler&tag=method:ping";
// todo: better fix needed: CDAP-2174
TimeUnit.SECONDS.sleep(1);
long received = getMetricValue(context, "system.request.received");
long successful = getMetricValue(context, "system.response.successful");
long clientError = getMetricValue(context, "system.response.client-error");
// Make a successful call
HttpResponse response = GatewayFastTestsSuite.doGet("/ping");
Assert.assertEquals(HttpResponseStatus.OK.getCode(), response.getStatusLine().getStatusCode());
// received and successful should have increased by one, clientError should be the same
verifyMetrics(received + 1, context, "system.request.received");
verifyMetrics(successful + 1, context, "system.response.successful");
verifyMetrics(clientError, context, "system.response.client-error");
}
@Test
public void testMetricsNotFound() throws Exception {
String context = "&tag=namespace:system&tag=component:appfabric&tag=handler:StreamHandler&tag=method:getInfo";
long received = getMetricValue(context, "system.request.received");
long successful = getMetricValue(context, "system.response.successful");
long clientError = getMetricValue(context, "system.response.client-error");
// Get info of non-existent stream
HttpResponse response = GatewayFastTestsSuite.doGet(
"/v3/namespaces/default/streams/metrics-hook-test-non-existent-stream");
Assert.assertEquals(HttpResponseStatus.NOT_FOUND.getCode(), response.getStatusLine().getStatusCode());
// received and clientError should have increased by one, successful should be the same
verifyMetrics(received + 1, context, "system.request.received");
verifyMetrics(successful, context, "system.response.successful");
verifyMetrics(clientError + 1, context, "system.response.client-error");
}
/**
* Verify metrics. It tries couple times to avoid race condition.
* This is because metrics hook is updated asynchronously.
*/
private void verifyMetrics(long expected, String context, String metricsName) throws Exception {
int trial = 0;
long metrics = -1;
while (trial++ < 5) {
metrics = getMetricValue(context, metricsName);
if (expected == metrics) {
return;
}
TimeUnit.SECONDS.sleep(1);
}
Assert.assertEquals(expected, metrics);
}
private static long getMetricValue(String context, String metricName) throws Exception {
HttpResponse response = doPost("/v3/metrics/query?" + context + "&metric=" + metricName);
Assert.assertEquals("POST " + context + " did not return 200 status.",
HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
String content = new String(ByteStreams.toByteArray(response.getEntity().getContent()), Charsets.UTF_8);
// response has the form:
// {"startTime":0,"endTime":...,"series":[{"metricName":"...","grouping":{},"data":[{"time":0,"value":<value>}]}]}
JsonObject json = new Gson().fromJson(content, JsonObject.class);
JsonArray array = json.getAsJsonArray("series");
if (array.size() > 0) {
array = array.get(0).getAsJsonObject().getAsJsonArray("data");
if (array.size() > 0) {
return array.get(0).getAsJsonObject().get("value").getAsLong();
}
}
return 0L;
}
public static HttpResponse doPost(String resource) throws Exception {
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(getEndPoint(resource));
post.setHeader(AUTH_HEADER);
return client.execute(post);
}
}