From ec68d12437611dd6fb817fa058020bb926b7e163 Mon Sep 17 00:00:00 2001 From: Liu Date: Fri, 27 Oct 2017 14:05:39 +0800 Subject: [PATCH 1/3] enhance kylin interpter, add error message parse --- kylin/pom.xml | 5 ++ .../zeppelin/kylin/KylinInterpreter.java | 46 +++++++++++-------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/kylin/pom.xml b/kylin/pom.xml index c3559cd04b8..3e8b6f1f65e 100644 --- a/kylin/pom.xml +++ b/kylin/pom.xml @@ -49,6 +49,11 @@ commons-codec commons-codec + + org.json + json + 20170516 + junit junit diff --git a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java index 6b68d288e47..5fca57ece4c 100755 --- a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java +++ b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java @@ -18,6 +18,7 @@ package org.apache.zeppelin.kylin; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; @@ -29,10 +30,10 @@ import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.json.JSONException; +import org.json.JSONObject; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStreamReader; import java.util.List; import java.util.Properties; import java.util.regex.Matcher; @@ -168,26 +169,31 @@ public String getSQL(String cmd) { private InterpreterResult executeQuery(String sql) throws IOException { HttpResponse response = prepareRequest(sql); - - if (response.getStatusLine().getStatusCode() != 200) { - logger.error("failed to execute query: " + response.getEntity().getContent().toString()); - return new InterpreterResult(InterpreterResult.Code.ERROR, - "Failed : HTTP error code " + response.getStatusLine().getStatusCode()); + String result = IOUtils.toString(response.getEntity().getContent(), "UTF-8"); + int code = response.getStatusLine().getStatusCode(); + if (code != 200) { + StringBuilder errorMessage = new StringBuilder("Failed : HTTP error code " + code); + logger.error("failed to execute query: " + result); + try { + JSONObject content = new JSONObject(result); + if (content.has("exception")) { + errorMessage.append(". Error message: " + content.getString("exception")); + } + } catch (JSONException e) { + logger.error("Cannot parse json string ", e); + // when code is 401, the response is html, not json + if (code == 401) { + errorMessage.append(". Error message: Unauthorized. This request requires " + + "HTTP authentication. Please make sure your have set your credentials correctly."); + } else { + errorMessage.append(". Error message: " + result); + } + } + return new InterpreterResult(InterpreterResult.Code.ERROR, errorMessage.toString()); } - BufferedReader br = new BufferedReader( - new InputStreamReader((response.getEntity().getContent()))); - StringBuilder sb = new StringBuilder(); - - String output; - logger.info("Output from Server .... \n"); - while ((output = br.readLine()) != null) { - logger.info(output); - sb.append(output).append('\n'); - } - InterpreterResult rett = new InterpreterResult(InterpreterResult.Code.SUCCESS, - formatResult(sb.toString())); - return rett; + return new InterpreterResult(InterpreterResult.Code.SUCCESS, + formatResult(result)); } String formatResult(String msg) { From cadaa2b9877da39d96db6b2e06f4169c9f604caf Mon Sep 17 00:00:00 2001 From: Liu Date: Fri, 27 Oct 2017 15:03:26 +0800 Subject: [PATCH 2/3] NPE bug fix when returned result set is empty --- .../zeppelin/kylin/KylinInterpreter.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java index 5fca57ece4c..3e693b49d66 100755 --- a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java +++ b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java @@ -211,17 +211,20 @@ String formatResult(String msg) { table = mr.group(1); } - String[] row = table.split("],\\["); - for (int i = 0; i < row.length; i++) { - String[] col = row[i].split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1); - for (int j = 0; j < col.length; j++) { - if (col[j] != null) { - col[j] = col[j].replaceAll("^\"|\"$", ""); + if (table != null && !table.isEmpty()) { + String[] row = table.split("],\\["); + for (int i = 0; i < row.length; i++) { + String[] col = row[i].split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1); + for (int j = 0; j < col.length; j++) { + if (col[j] != null) { + col[j] = col[j].replaceAll("^\"|\"$", ""); + } + res.append(col[j] + " \t"); } - res.append(col[j] + " \t"); + res.append(" \n"); } - res.append(" \n"); } + return res.toString(); } From 933c9d872e67d64d9e646cb287a66f2d7593a54a Mon Sep 17 00:00:00 2001 From: Liu Date: Tue, 31 Oct 2017 13:45:48 +0800 Subject: [PATCH 3/3] use gson --- kylin/pom.xml | 5 -- .../zeppelin/kylin/KylinErrorResponse.java | 66 +++++++++++++++++++ .../zeppelin/kylin/KylinInterpreter.java | 48 ++++++++------ 3 files changed, 94 insertions(+), 25 deletions(-) create mode 100644 kylin/src/main/java/org/apache/zeppelin/kylin/KylinErrorResponse.java diff --git a/kylin/pom.xml b/kylin/pom.xml index 3e8b6f1f65e..c3559cd04b8 100644 --- a/kylin/pom.xml +++ b/kylin/pom.xml @@ -49,11 +49,6 @@ commons-codec commons-codec - - org.json - json - 20170516 - junit junit diff --git a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinErrorResponse.java b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinErrorResponse.java new file mode 100644 index 00000000000..55e334b8f62 --- /dev/null +++ b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinErrorResponse.java @@ -0,0 +1,66 @@ +/* + * 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.zeppelin.kylin; + + +import static org.apache.zeppelin.interpreter.Interpreter.logger; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import org.apache.zeppelin.common.JsonSerializable; + +/** + * class for Kylin Error Response. + */ +class KylinErrorResponse implements JsonSerializable { + private static final Gson gson = new Gson(); + + private String stacktrace; + private String exception; + private String url; + private String code; + private Object data; + private String msg; + + public KylinErrorResponse(String stacktrace, String exception, String url, + String code, Object data, String msg) { + this.stacktrace = stacktrace; + this.exception = exception; + this.url = url; + this.code = code; + this.data = data; + this.msg = msg; + } + + public String getException() { + return exception; + } + + public String toJson() { + return gson.toJson(this); + } + + public static KylinErrorResponse fromJson(String json) { + try { + return gson.fromJson(json, KylinErrorResponse.class); + } catch (JsonSyntaxException ex) { + return null; + } + } + +} diff --git a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java index 3e693b49d66..5b3581ddc8d 100755 --- a/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java +++ b/kylin/src/main/java/org/apache/zeppelin/kylin/KylinInterpreter.java @@ -30,8 +30,6 @@ import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.json.JSONException; -import org.json.JSONObject; import java.io.IOException; import java.util.List; @@ -169,27 +167,37 @@ public String getSQL(String cmd) { private InterpreterResult executeQuery(String sql) throws IOException { HttpResponse response = prepareRequest(sql); - String result = IOUtils.toString(response.getEntity().getContent(), "UTF-8"); - int code = response.getStatusLine().getStatusCode(); - if (code != 200) { - StringBuilder errorMessage = new StringBuilder("Failed : HTTP error code " + code); - logger.error("failed to execute query: " + result); - try { - JSONObject content = new JSONObject(result); - if (content.has("exception")) { - errorMessage.append(". Error message: " + content.getString("exception")); - } - } catch (JSONException e) { - logger.error("Cannot parse json string ", e); - // when code is 401, the response is html, not json - if (code == 401) { - errorMessage.append(". Error message: Unauthorized. This request requires " - + "HTTP authentication. Please make sure your have set your credentials correctly."); + String result; + + try { + int code = response.getStatusLine().getStatusCode(); + result = IOUtils.toString(response.getEntity().getContent(), "UTF-8"); + + if (code != 200) { + StringBuilder errorMessage = new StringBuilder("Failed : HTTP error code " + code); + logger.error("Failed to execute query: " + result); + + KylinErrorResponse kylinErrorResponse = KylinErrorResponse.fromJson(result); + if (kylinErrorResponse == null) { + logger.error("Cannot get json from string: " + result); + // when code is 401, the response is html, not json + if (code == 401) { + errorMessage.append(". Error message: Unauthorized. This request requires " + + "HTTP authentication. Please make sure your have set your credentials" + + " correctly."); + } else { + errorMessage.append(". Error message: " + result); + } } else { - errorMessage.append(". Error message: " + result); + String exception = kylinErrorResponse.getException(); + logger.error("The exception is " + exception); + errorMessage.append(". Error message: " + exception); } + + return new InterpreterResult(InterpreterResult.Code.ERROR, errorMessage.toString()); } - return new InterpreterResult(InterpreterResult.Code.ERROR, errorMessage.toString()); + } catch (NullPointerException | IOException e) { + throw new IOException(e); } return new InterpreterResult(InterpreterResult.Code.SUCCESS,