/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.lens.server.metrics;
import static org.testng.Assert.*;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotAllowedException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.MediaType;
import org.apache.lens.api.APIResult;
import org.apache.lens.api.LensConf;
import org.apache.lens.api.LensSessionHandle;
import org.apache.lens.api.query.QueryHandle;
import org.apache.lens.api.result.LensAPIResult;
import org.apache.lens.server.LensAllApplicationJerseyTest;
import org.apache.lens.server.LensApplication;
import org.apache.lens.server.LensServerTestUtil;
import org.apache.lens.server.LensServices;
import org.apache.lens.server.api.metastore.CubeMetastoreService;
import org.apache.lens.server.api.metrics.MethodMetrics;
import org.apache.lens.server.api.metrics.MetricsService;
import org.apache.lens.server.common.TestResourceFile;
import org.apache.lens.server.metastore.CubeMetastoreServiceImpl;
import org.apache.lens.server.query.TestQueryService;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.test.TestProperties;
import org.testng.Assert;
import org.testng.annotations.*;
import lombok.extern.slf4j.Slf4j;
@Test(groups = "unit-test")
@Slf4j
public class TestResourceMethodMetrics extends LensAllApplicationJerseyTest {
private CubeMetastoreServiceImpl metastoreService;
private MetricsServiceImpl metricsSvc;
private LensSessionHandle lensSessionId;
protected String mediaType = MediaType.APPLICATION_XML;
private Map<String, MethodMetrics> methodMetricsMap;
/*
* (non-Javadoc)
*
* @see org.glassfish.jersey.test.JerseyTest#setUp()
*/
@BeforeTest
public void setUp() throws Exception {
super.setUp();
}
@BeforeClass
public void create() throws Exception {
metricsSvc = LensServices.get().getService(MetricsService.NAME);
metastoreService = LensServices.get().getService(CubeMetastoreService.NAME);
lensSessionId = metastoreService.openSession("foo", "bar", new HashMap<String, String>());
methodMetricsMap = metricsSvc.getMethodMetricsFactory().getMethodMetricsMap();
//reset
}
private void createTable(String tblName) throws InterruptedException {
LensServerTestUtil.createTable(tblName, target(), lensSessionId, defaultMT);
}
private void loadData(String tblName, final String testDataFile) throws InterruptedException {
LensServerTestUtil.loadDataFromClasspath(tblName, testDataFile, target(), lensSessionId, defaultMT);
}
@AfterTest
public void tearDown() throws Exception {
super.tearDown();
}
@AfterClass
public void drop() throws Exception {
LensServerTestUtil.dropTable(TestQueryService.TEST_TABLE, target(), lensSessionId, defaultMT);
metastoreService.closeSession(lensSessionId);
}
private void disableResourceMethodMetering() {
metricsSvc.setEnableResourceMethodMetering(false);
Assert.assertEquals(methodMetricsMap.size(), 0);
Assert.assertEquals(metricsSvc.getMetricRegistry().getMeters().size(), 0);
Assert.assertEquals(metricsSvc.getMetricRegistry().getTimers().size(), 0);
}
@Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
return new LensApplication();
}
@Test
public void test() throws Exception {
boolean enabled = metricsSvc.isEnableResourceMethodMetering();
disableResourceMethodMetering();
metricsSvc.setEnableResourceMethodMetering(true);
Assert.assertEquals(methodMetricsMap.size(), 0);
log.info("database operations");
databaseOperations();
Assert.assertEquals(methodMetricsMap.size(), 3);
log.info("create table");
createTable(TestQueryService.TEST_TABLE);
Assert.assertEquals(methodMetricsMap.size(), 5);
log.info("load data");
loadData(TestQueryService.TEST_TABLE, TestResourceFile.TEST_DATA2_FILE.getValue());
Assert.assertEquals(methodMetricsMap.size(), 5);
log.info("execute async");
executeAsync();
verifyValues();
makeClientError();
// no change in values
verifyValues();
disableResourceMethodMetering();
metricsSvc.setEnableResourceMethodMetering(enabled);
}
private void makeClientError() throws Exception {
WebTarget dbTarget = target().path("metastore").path("databases/blah");
try {
dbTarget.queryParam("sessionid", lensSessionId).request(mediaType).get(APIResult.class);
fail("Should get 404");
} catch (NotAllowedException e) {
// expected
log.error("Not found excepiton:", e);
}
}
private void verifyValues() throws InterruptedException {
// wait for values to stabilize
Thread.sleep(5);
Assert.assertEquals(methodMetricsMap.size(), 5);
// 2 for each
Assert.assertEquals(metricsSvc.getMetricRegistry().getTimers().size(), 10);
// 1 for each
Assert.assertEquals(metricsSvc.getMetricRegistry().getMeters().size(), 5);
Assert.assertFalse(methodMetricsMap.containsKey(
"org.apache.lens.server.query.QueryServiceResource.query.POST.EXPLAIN"));
Assert.assertEquals(methodMetricsMap.get("org.apache.lens.server.metastore.MetastoreResource.setDatabase.PUT")
.getSuccessCount(), 2);
Assert.assertEquals(methodMetricsMap.get(
"org.apache.lens.server.metastore.MetastoreResource.setDatabase.PUT").getErrorCount(), 2);
Assert.assertEquals(methodMetricsMap.get("org.apache.lens.server.metastore.MetastoreResource.getDatabase.GET")
.getSuccessCount(), 2);
Assert.assertEquals(methodMetricsMap.get(
"org.apache.lens.server.metastore.MetastoreResource.getDatabase.GET").getErrorCount(), 0);
Assert.assertTrue(methodMetricsMap.get("org.apache.lens.server.query.QueryServiceResource.getStatus.GET")
.getSuccessCount() >= 0);
Assert.assertEquals(methodMetricsMap.get(
"org.apache.lens.server.query.QueryServiceResource.getStatus.GET").getErrorCount(), 0);
Assert.assertEquals(methodMetricsMap.get(
"org.apache.lens.server.metastore.MetastoreResource.createDatabase.POST").getSuccessCount(), 1);
Assert.assertEquals(methodMetricsMap.get(
"org.apache.lens.server.metastore.MetastoreResource.createDatabase.POST").getErrorCount(), 0);
Assert.assertEquals(methodMetricsMap.get(
"org.apache.lens.server.query.QueryServiceResource.query.POST.EXECUTE").getSuccessCount(), 3);
Assert.assertEquals(methodMetricsMap.get(
"org.apache.lens.server.query.QueryServiceResource.query.POST.EXECUTE").getErrorCount(), 0);
for (String key : methodMetricsMap.keySet()) {
long count = methodMetricsMap.get(key).getCount();
long success = methodMetricsMap.get(key).getSuccessCount();
long errors = methodMetricsMap.get(key).getErrorCount();
Assert.assertEquals(count, success + errors, "Total:" + count + ", success: " + success
+ ", errors: " + errors);
}
}
private void databaseOperations() throws Exception {
String prevDb = getCurrentDatabase();
WebTarget dbTarget = target().path("metastore").path("databases/current");
String dbName = "random_" + UUID.randomUUID().toString().substring(0, 6);
try {
dbTarget.queryParam("sessionid", lensSessionId).request(mediaType).put(Entity.xml(dbName), APIResult.class);
fail("Should get 404");
} catch (NotFoundException e) {
// expected
}
// create
APIResult result = target().path("metastore").path("databases")
.queryParam("sessionid", lensSessionId).request(mediaType).post(Entity.xml(dbName), APIResult.class);
assertNotNull(result);
assertEquals(result.getStatus(), APIResult.Status.SUCCEEDED);
// set
result = dbTarget.queryParam("sessionid", lensSessionId).request(mediaType)
.put(Entity.xml(dbName), APIResult.class);
assertNotNull(result);
assertEquals(result.getStatus(), APIResult.Status.SUCCEEDED);
// set without session id, we should get bad request
try {
result = dbTarget.request(mediaType).put(Entity.xml(dbName), APIResult.class);
fail("Should have thrown bad request exception");
} catch (BadRequestException badReq) {
// expected
}
String current = dbTarget.queryParam("sessionid", lensSessionId).request(mediaType).get(String.class);
assertEquals(current, dbName);
setCurrentDatabase(prevDb);
}
private void executeAsync() {
final WebTarget target = target().path("queryapi/queries");
final FormDataMultiPart mp = new FormDataMultiPart();
mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("sessionid").build(), lensSessionId,
MediaType.APPLICATION_XML_TYPE));
mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("query").build(), "select ID, IDSTR from "
+ TestQueryService.TEST_TABLE));
mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("operation").build(), "execute"));
mp.bodyPart(new FormDataBodyPart(FormDataContentDisposition.name("conf").fileName("conf").build(), new LensConf(),
MediaType.APPLICATION_XML_TYPE));
final QueryHandle handle = target.request(mediaType).post(Entity.entity(mp, MediaType.MULTIPART_FORM_DATA_TYPE),
new GenericType<LensAPIResult<QueryHandle>>() {}).getData();
Assert.assertNotNull(handle);
}
private String getCurrentDatabase() throws Exception {
WebTarget dbTarget = target().path("metastore").path("databases/current");
Invocation.Builder builder = dbTarget.queryParam("sessionid", lensSessionId).request(mediaType);
String response = builder.get(String.class);
return response;
}
private void setCurrentDatabase(String dbName) throws Exception {
WebTarget dbTarget = target().path("metastore").path("databases/current");
APIResult result = dbTarget.queryParam("sessionid", lensSessionId).request(mediaType).put(Entity.xml(dbName),
APIResult.class);
assertEquals(result.getStatus(), APIResult.Status.SUCCEEDED);
}
}