blob: 86425ad7754a8f4578d1d78d88b8f6d062d30ab3 [file] [log] [blame]
/*
* 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.hive.service.cli.session;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hadoop.hive.ql.QueryDisplay;
import org.apache.hadoop.hive.ql.QueryInfo;
import org.apache.hadoop.hive.ql.exec.Task;
import org.apache.hadoop.hive.ql.exec.TaskResult;
import org.apache.hadoop.hive.ql.log.PerfLogger;
import org.apache.hadoop.hive.ql.plan.api.StageType;
import org.apache.hadoop.hive.ql.session.SessionState;
import org.apache.hive.service.cli.OperationHandle;
import org.apache.hive.service.cli.SessionHandle;
import org.apache.hive.service.rpc.thrift.TProtocolVersion;
import org.apache.hive.tmpl.QueryProfileTmpl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
/**
* Test QueryDisplay and its consumers like WebUI.
*/
public class TestQueryDisplay {
private HiveConf conf;
private SessionManager sessionManager;
@Before
public void setup() {
conf = new HiveConf();
conf.set("hive.support.concurrency", "false");
sessionManager = new SessionManager(null, true);
sessionManager.init(conf);
sessionManager.start();
}
/**
* Test if query display captures information on current/historic SQL operations.
*/
@Test
public void testQueryDisplay() throws Exception {
HiveSession session = sessionManager
.createSession(new SessionHandle(TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8),
TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8, "testuser", "", "",
new HashMap<String, String>(), false, "");
session.getSessionState().setIsHiveServerQuery(false);
SessionState.start(conf);
OperationHandle opHandle1 = session.executeStatement("show databases", null);
SessionState.start(conf);
OperationHandle opHandle2 = session.executeStatement("show tables", null);
List<QueryInfo> liveSqlOperations, historicSqlOperations;
liveSqlOperations = sessionManager.getOperationManager().getLiveQueryInfos();
historicSqlOperations = sessionManager.getOperationManager().getHistoricalQueryInfos();
Assert.assertEquals(liveSqlOperations.size(), 2);
Assert.assertEquals(historicSqlOperations.size(), 0);
verifyDDL(liveSqlOperations.get(0), "show databases", opHandle1.getHandleIdentifier().toString(), false);
verifyDDL(liveSqlOperations.get(1), "show tables", opHandle2.getHandleIdentifier().toString(), false);
session.closeOperation(opHandle1);
liveSqlOperations = sessionManager.getOperationManager().getLiveQueryInfos();
historicSqlOperations = sessionManager.getOperationManager().getHistoricalQueryInfos();
Assert.assertEquals(liveSqlOperations.size(), 1);
Assert.assertEquals(historicSqlOperations.size(), 1);
verifyDDL(historicSqlOperations.get(0), "show databases", opHandle1.getHandleIdentifier().toString(), true);
verifyDDL(liveSqlOperations.get(0), "show tables", opHandle2.getHandleIdentifier().toString(), false);
session.closeOperation(opHandle2);
liveSqlOperations = sessionManager.getOperationManager().getLiveQueryInfos();
historicSqlOperations = sessionManager.getOperationManager().getHistoricalQueryInfos();
Assert.assertEquals(liveSqlOperations.size(), 0);
Assert.assertEquals(historicSqlOperations.size(), 2);
verifyDDL(historicSqlOperations.get(1), "show databases", opHandle1.getHandleIdentifier().toString(), true);
verifyDDL(historicSqlOperations.get(0), "show tables", opHandle2.getHandleIdentifier().toString(), true);
session.close();
}
/**
* Test if webui captures information on current/historic SQL operations.
*/
@Test
public void testWebUI() throws Exception {
HiveSession session = sessionManager
.createSession(new SessionHandle(TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8),
TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8, "testuser", "", "",
new HashMap<String, String>(), false, "");
SessionState.start(conf);
OperationHandle opHandle1 = session.executeStatement("show databases", null);
SessionState.start(conf);
OperationHandle opHandle2 = session.executeStatement("show tables", null);
verifyDDLHtml("show databases", opHandle1.getHandleIdentifier().toString());
verifyDDLHtml("show tables", opHandle2.getHandleIdentifier().toString());
session.closeOperation(opHandle1);
session.closeOperation(opHandle2);
verifyDDLHtml("show databases", opHandle1.getHandleIdentifier().toString());
verifyDDLHtml("show tables", opHandle2.getHandleIdentifier().toString());
session.close();
}
/**
* Test for the HiveConf option HIVE_SERVER2_WEBUI_EXPLAIN_OUTPUT.
*/
@Test
public void checkWebuiExplainOutput() throws Exception {
//check cases when HIVE_SERVER2_WEBUI_EXPLAIN_OUTPUT is set and not set
boolean[] webuiExplainConfValues = new boolean[]{true, false};
for (boolean confValue : webuiExplainConfValues) {
conf.setBoolVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_EXPLAIN_OUTPUT, confValue);
HiveSession session = sessionManager
.createSession(new SessionHandle(TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8),
TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8, "testuser", "", "",
new HashMap<String, String>(), false, "");
SessionState.start(conf);
OperationHandle opHandle = session.executeStatement("show tables", null);
session.closeOperation(opHandle);
//STAGE PLANS is something which will be shown as part of EXPLAIN query
verifyDDLHtml("STAGE PLANS", opHandle.getHandleIdentifier().toString(), confValue);
//Check that the following message is not shown when this option is set
verifyDDLHtml(
"Set configuration hive.server2.webui.explain.output to true to view future query plans",
opHandle.getHandleIdentifier().toString(), !confValue);
session.close();
}
}
/**
* Test for the HiveConf options HIVE_SERVER2_WEBUI_SHOW_GRAPH,
* HIVE_SERVER2_WEBUI_MAX_GRAPH_SIZE.
*/
@Test
public void checkWebuiShowGraph() throws Exception {
// WebUI-related boolean confs must be set before build, since the implementation of
// QueryProfileTmpl.jamon depends on them.
// They depend on HIVE_SERVER2_WEBUI_EXPLAIN_OUTPUT being set to true.
conf.setBoolVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_EXPLAIN_OUTPUT, true);
conf.setBoolVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_SHOW_GRAPH, true);
HiveSession session = sessionManager
.createSession(new SessionHandle(TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8),
TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8, "testuser", "", "",
new HashMap<String, String>(), false, "");
SessionState.start(conf);
session.getSessionConf()
.setIntVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_MAX_GRAPH_SIZE, 0);
testGraphDDL(session, true);
session.getSessionConf()
.setIntVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_MAX_GRAPH_SIZE, 40);
testGraphDDL(session, false);
session.close();
resetConfToDefaults();
}
private void testGraphDDL(HiveSession session, boolean exceedMaxGraphSize) throws Exception {
OperationHandle opHandleGraph = session.executeStatement("show tables", null);
session.closeOperation(opHandleGraph);
// Check for a query plan. If the graph size exceeds the max allowed, none should appear.
verifyDDLHtml("Query information not available.",
opHandleGraph.getHandleIdentifier().toString(), exceedMaxGraphSize);
verifyDDLHtml("STAGE DEPENDENCIES",
opHandleGraph.getHandleIdentifier().toString(), !exceedMaxGraphSize);
// Check that if plan Json is there, it is not empty
verifyDDLHtml("jsonPlan = {}", opHandleGraph.getHandleIdentifier().toString(), false);
}
/**
* Test for the HiveConf option HIVE_SERVER2_WEBUI_SHOW_STATS, which is available for MapReduce
* jobs only.
*/
@Test
public void checkWebUIShowStats() throws Exception {
// WebUI-related boolean confs must be set before build. HIVE_SERVER2_WEBUI_SHOW_STATS depends
// on HIVE_SERVER2_WEBUI_EXPLAIN_OUTPUT and HIVE_SERVER2_WEBUI_SHOW_GRAPH being set to true.
conf.setVar(HiveConf.ConfVars.HIVE_EXECUTION_ENGINE, "mr");
conf.setBoolVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_EXPLAIN_OUTPUT, true);
conf.setBoolVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_SHOW_GRAPH, true);
conf.setIntVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_MAX_GRAPH_SIZE, 40);
conf.setBoolVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_SHOW_STATS, true);
HiveSession session = sessionManager
.createSession(new SessionHandle(TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8),
TProtocolVersion.HIVE_CLI_SERVICE_PROTOCOL_V8, "testuser", "", "",
new HashMap<String, String>(), false, "");
SessionState.start(conf);
OperationHandle opHandleSetup =
session.executeStatement("CREATE TABLE statsTable (i int)", null);
session.closeOperation(opHandleSetup);
OperationHandle opHandleMrQuery =
session.executeStatement("INSERT INTO statsTable VALUES (0)", null);
session.closeOperation(opHandleMrQuery);
// INSERT queries include a MapReduce task.
verifyDDLHtml("Counters", opHandleMrQuery.getHandleIdentifier().toString(), true);
session.close();
resetConfToDefaults();
}
private void resetConfToDefaults() {
conf.setBoolVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_EXPLAIN_OUTPUT, false);
conf.setBoolVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_SHOW_GRAPH, false);
conf.setBoolVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_SHOW_STATS, false);
conf.setIntVar(HiveConf.ConfVars.HIVE_SERVER2_WEBUI_MAX_GRAPH_SIZE, 25);
}
private void verifyDDL(QueryInfo queryInfo, String stmt, String handle, boolean finished) {
Assert.assertEquals(queryInfo.getUserName(), "testuser");
Assert.assertEquals(queryInfo.getExecutionEngine(), "mr");
Assert.assertEquals(queryInfo.getOperationId(), handle);
Assert.assertTrue(queryInfo.getBeginTime() > 0 && queryInfo.getBeginTime() <= System.currentTimeMillis());
if (finished) {
Assert.assertTrue(
queryInfo.getEndTime() > 0 && queryInfo.getEndTime() >= queryInfo.getBeginTime()
&& queryInfo.getEndTime() <= System.currentTimeMillis());
Assert.assertTrue(queryInfo.getRuntime() > 0);
} else {
Assert.assertNull(queryInfo.getEndTime());
//For runtime, query may have finished.
}
QueryDisplay qDisplay1 = queryInfo.getQueryDisplay();
Assert.assertNotNull(qDisplay1);
Assert.assertEquals(qDisplay1.getQueryString(), stmt);
Assert.assertNotNull(qDisplay1.getExplainPlan());
Assert.assertNull(qDisplay1.getErrorMessage());
Assert.assertTrue(qDisplay1.getHmsTimings(QueryDisplay.Phase.COMPILATION).size() > 0);
Assert.assertTrue(qDisplay1.getHmsTimings(QueryDisplay.Phase.EXECUTION).size() > 0);
Assert.assertTrue(qDisplay1.getPerfLogStarts(QueryDisplay.Phase.COMPILATION).size() > 0);
Assert.assertTrue(qDisplay1.getPerfLogEnds(QueryDisplay.Phase.COMPILATION).size() > 0);
Assert.assertTrue(qDisplay1.getPerfLogStarts(QueryDisplay.Phase.COMPILATION).size() > 0);
Assert.assertTrue(qDisplay1.getPerfLogEnds(QueryDisplay.Phase.COMPILATION).size() > 0);
Assert.assertTrue(qDisplay1.getPerfLogStarts(QueryDisplay.Phase.COMPILATION).containsKey(PerfLogger.COMPILE));
Assert.assertFalse(qDisplay1.getPerfLogStarts(QueryDisplay.Phase.EXECUTION).containsKey(PerfLogger.COMPILE));
Assert.assertTrue(qDisplay1.getPerfLogStarts(QueryDisplay.Phase.EXECUTION).containsKey(PerfLogger.DRIVER_EXECUTE));
Assert.assertFalse(qDisplay1.getPerfLogStarts(QueryDisplay.Phase.COMPILATION)
.containsKey(PerfLogger.DRIVER_EXECUTE));
Assert.assertEquals(qDisplay1.getTaskDisplays().size(), 1);
QueryDisplay.TaskDisplay tInfo1 = qDisplay1.getTaskDisplays().get(0);
Assert.assertEquals(tInfo1.getTaskId(), "Stage-0");
Assert.assertEquals(tInfo1.getTaskType(), StageType.DDL);
Assert.assertTrue(tInfo1.getBeginTime() > 0 && tInfo1.getBeginTime() <= System.currentTimeMillis());
Assert.assertTrue(tInfo1.getEndTime() > 0 && tInfo1.getEndTime() >= tInfo1.getBeginTime()
&& tInfo1.getEndTime() <= System.currentTimeMillis());
Assert.assertEquals(tInfo1.getStatus(), "Success, ReturnVal 0");
}
/**
* Sanity check if basic information is delivered in this html. Let's not go too crazy and
* assert each element, to make it easier to add UI improvements.
*/
private void verifyDDLHtml(String stmt, String opHandle) throws Exception {
verifyDDLHtml(stmt, opHandle, true);
}
private void verifyDDLHtml(String stmt, String opHandle, boolean assertCondition) throws Exception {
StringWriter sw = new StringWriter();
QueryInfo queryInfo = sessionManager.getOperationManager().getQueryInfo(opHandle);
HiveConf hiveConf = sessionManager.getOperationManager().getHiveConf();
new QueryProfileTmpl().render(sw, queryInfo, hiveConf);
String html = sw.toString();
Assert.assertEquals(assertCondition, html.contains(stmt));
Assert.assertTrue(html.contains("testuser"));
}
static class MyTask extends Task<Integer> {
public MyTask() {
id = "x";
}
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public String getName() {
return "my";
}
@Override
public int execute() {
return 0;
}
@Override
public StageType getType() {
return StageType.ATLAS_DUMP;
}
}
@Test
public void testJSONSerialization() throws Exception {
QueryDisplay qd = new QueryDisplay();
qd.setErrorMessage("asd");
qd.setTaskResult("a", new TaskResult());
qd.setExplainPlan("explainPlan");
qd.setQueryStr("qstr");
Task<?> tTask = new MyTask();
qd.updateTaskStatus(tTask);
tTask.setStarted();
qd.updateTaskStatus(tTask);
tTask.setDone();
qd.updateTaskStatus(tTask);
Long ee = qd.getTaskDisplays().get(0).getElapsedTime();
System.out.println(ee);
String json = QueryDisplay.OBJECT_MAPPER.writeValueAsString(qd);
QueryDisplay n = QueryDisplay.OBJECT_MAPPER.readValue(json, QueryDisplay.class);
assertEquals(qd.getQueryString(), n.getQueryString());
assertEquals(qd.getExplainPlan(), n.getExplainPlan());
assertEquals(qd.getErrorMessage(), n.getErrorMessage());
assertEquals(qd.getTaskDisplays().size(), n.getTaskDisplays().size());
assertEquals(qd.getTaskDisplays().get(0).taskState, n.getTaskDisplays().get(0).taskState);
}
}