Repository: incubator-hivemall
Updated Branches:
  refs/heads/v0.5.0 b246527c2 -> 464d08912


Fixed to show stacktrace on exception


Project: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-hivemall/commit/464d0891
Tree: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/tree/464d0891
Diff: http://git-wip-us.apache.org/repos/asf/incubator-hivemall/diff/464d0891

Branch: refs/heads/v0.5.0
Commit: 464d08912bc55d9c6192e7d786bdfe10efde3002
Parents: b246527
Author: Makoto Yui <[email protected]>
Authored: Thu Jan 18 21:38:04 2018 +0900
Committer: Makoto Yui <[email protected]>
Committed: Thu Jan 18 21:38:04 2018 +0900

----------------------------------------------------------------------
 .../hivemall/utils/lang/ExceptionUtils.java     | 118 +++++++++++++++++++
 .../hivemall/nlp/tokenizer/KuromojiUDF.java     |  48 ++++----
 2 files changed, 145 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/464d0891/core/src/main/java/hivemall/utils/lang/ExceptionUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/hivemall/utils/lang/ExceptionUtils.java 
b/core/src/main/java/hivemall/utils/lang/ExceptionUtils.java
new file mode 100644
index 0000000..b69c5b0
--- /dev/null
+++ b/core/src/main/java/hivemall/utils/lang/ExceptionUtils.java
@@ -0,0 +1,118 @@
+/*
+ * 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 hivemall.utils.lang;
+
+import javax.annotation.Nonnull;
+
+public final class ExceptionUtils {
+
+    public static final int TRACE_CAUSE_DEPTH = 5;
+
+    private ExceptionUtils() {}
+
+    @Nonnull
+    public static String prettyPrintStackTrace(@Nonnull final Throwable 
throwable) {
+        return prettyPrintStackTrace(throwable, TRACE_CAUSE_DEPTH);
+    }
+
+    @Nonnull
+    public static String prettyPrintStackTrace(@Nonnull final Throwable 
throwable,
+            final int traceDepth) {
+        final StringBuilder out = new StringBuilder(512);
+        out.append(getMessage(throwable));
+        out.append("\n\n---- Debugging information ----");
+        final int tracedepth;
+        if (throwable instanceof RuntimeException || throwable instanceof 
Error) {
+            tracedepth = -1;
+        } else {
+            tracedepth = traceDepth;
+        }
+        String captured = captureThrownWithStrackTrace(throwable, 
"trace-exception", tracedepth);
+        out.append(captured);
+        final Throwable cause = throwable.getCause();
+        if (cause != null) {
+            final Throwable rootCause = getRootCause(cause);
+            captured = captureThrownWithStrackTrace(rootCause, "trace-cause", 
TRACE_CAUSE_DEPTH);
+            out.append(captured);
+        }
+        out.append("\n------------------------------- \n");
+        return out.toString();
+    }
+
+    @Nonnull
+    private static String captureThrownWithStrackTrace(@Nonnull final 
Throwable throwable,
+            final String label, final int traceDepth) {
+        assert (traceDepth >= 1 || traceDepth == -1);
+        final StringBuilder out = new StringBuilder(255);
+        final String clazz = throwable.getClass().getName();
+        out.append(String.format("\n%-20s: %s \n", ("* " + label), clazz));
+        final StackTraceElement[] st = throwable.getStackTrace();
+        int at;
+        final int limit = (traceDepth == -1) ? st.length - 1 : traceDepth;
+        for (at = 0; at < st.length; at++) {
+            if (at < limit) {
+                out.append("\tat " + st[at] + '\n');
+            } else {
+                out.append("\t...\n");
+                break;
+            }
+        }
+        if (st.length == 0) {
+            out.append("\t no stack traces...");
+        } else if (at != (st.length - 1)) {
+            out.append("\tat " + st[st.length - 1]);
+        }
+        String errmsg = throwable.getMessage();
+        if (errmsg != null) {
+            out.append(String.format("\n%-20s: \n", ("* " + label + 
"-error-msg")));
+            String[] line = errmsg.split("\n");
+            final int maxlines = Math.min(line.length, Math.max(1, 
TRACE_CAUSE_DEPTH - 2));
+            for (int i = 0; i < maxlines; i++) {
+                out.append('\t');
+                out.append(line[i]);
+                if (i != (maxlines - 1)) {
+                    out.append('\n');
+                }
+            }
+        }
+        return out.toString();
+    }
+
+    @Nonnull
+    public static String getMessage(@Nonnull final Throwable throwable) {
+        String errMsg = throwable.getMessage();
+        String clazz = throwable.getClass().getName();
+        return (errMsg != null) ? clazz + ": " + errMsg : clazz;
+    }
+
+    @Nonnull
+    private static Throwable getRootCause(@Nonnull final Throwable throwable) {
+        Throwable top = throwable;
+        while (top != null) {
+            Throwable parent = top.getCause();
+            if (parent != null) {
+                top = parent;
+            } else {
+                break;
+            }
+        }
+        return top;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-hivemall/blob/464d0891/nlp/src/main/java/hivemall/nlp/tokenizer/KuromojiUDF.java
----------------------------------------------------------------------
diff --git a/nlp/src/main/java/hivemall/nlp/tokenizer/KuromojiUDF.java 
b/nlp/src/main/java/hivemall/nlp/tokenizer/KuromojiUDF.java
index 93fd18c..f56568b 100644
--- a/nlp/src/main/java/hivemall/nlp/tokenizer/KuromojiUDF.java
+++ b/nlp/src/main/java/hivemall/nlp/tokenizer/KuromojiUDF.java
@@ -18,13 +18,9 @@
  */
 package hivemall.nlp.tokenizer;
 
-import hivemall.utils.hadoop.HiveUtils;
-import hivemall.utils.io.IOUtils;
-import hivemall.utils.io.HttpUtils;
-
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.IOException;
 import java.io.Reader;
 import java.io.StringReader;
 import java.net.HttpURLConnection;
@@ -55,8 +51,12 @@ import org.apache.lucene.analysis.ja.dict.UserDictionary;
 import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
 import org.apache.lucene.analysis.util.CharArraySet;
 
-@Description(
-        name = "tokenize_ja",
+import hivemall.utils.hadoop.HiveUtils;
+import hivemall.utils.io.HttpUtils;
+import hivemall.utils.io.IOUtils;
+import hivemall.utils.lang.ExceptionUtils;
+
+@Description(name = "tokenize_ja",
         value = "_FUNC_(String line [, const string mode = \"normal\", const 
array<string> stopWords, const array<string> stopTags, const array<string> 
userDict (or string userDictURL)])"
                 + " - returns tokenized strings in array<string>")
 @UDFType(deterministic = true, stateful = false)
@@ -77,20 +77,21 @@ public final class KuromojiUDF extends GenericUDF {
     public ObjectInspector initialize(ObjectInspector[] arguments) throws 
UDFArgumentException {
         final int arglen = arguments.length;
         if (arglen < 1 || arglen > 5) {
-            throw new UDFArgumentException("Invalid number of arguments for 
`tokenize_ja`: "
-                    + arglen);
+            throw new UDFArgumentException(
+                "Invalid number of arguments for `tokenize_ja`: " + arglen);
         }
 
         this._mode = (arglen >= 2) ? tokenizationMode(arguments[1]) : 
Mode.NORMAL;
-        this._stopWords = (arglen >= 3) ? stopWords(arguments[2])
-                : JapaneseAnalyzer.getDefaultStopSet();
-        this._stopTags = (arglen >= 4) ? stopTags(arguments[3])
-                : JapaneseAnalyzer.getDefaultStopTags();
+        this._stopWords =
+                (arglen >= 3) ? stopWords(arguments[2]) : 
JapaneseAnalyzer.getDefaultStopSet();
+        this._stopTags =
+                (arglen >= 4) ? stopTags(arguments[3]) : 
JapaneseAnalyzer.getDefaultStopTags();
         this._userDict = (arglen >= 5) ? userDictionary(arguments[4]) : null;
 
         this._analyzer = null;
 
-        return 
ObjectInspectorFactory.getStandardListObjectInspector(PrimitiveObjectInspectorFactory.writableStringObjectInspector);
+        return ObjectInspectorFactory.getStandardListObjectInspector(
+            PrimitiveObjectInspectorFactory.writableStringObjectInspector);
     }
 
     @Override
@@ -219,7 +220,8 @@ public final class KuromojiUDF extends GenericUDF {
             return UserDictionary.open(reader); // return null if empty
         } catch (Throwable e) {
             throw new UDFArgumentException(
-                "Failed to create user dictionary based on the given 
array<string>: " + e);
+                "Failed to create user dictionary based on the given 
array<string>: "
+                        + builder.toString() + '\n' + 
ExceptionUtils.prettyPrintStackTrace(e));
         }
     }
 
@@ -234,7 +236,8 @@ public final class KuromojiUDF extends GenericUDF {
         try {
             conn = HttpUtils.getHttpURLConnection(userDictURL);
         } catch (IllegalArgumentException | IOException e) {
-            throw new UDFArgumentException("Failed to create HTTP connection 
to the URL: " + e);
+            throw new UDFArgumentException("Failed to create HTTP connection 
to the URL: "
+                    + userDictURL + '\n' + 
ExceptionUtils.prettyPrintStackTrace(e));
         }
 
         // allow to read as a compressed GZIP file for efficiency
@@ -247,7 +250,8 @@ public final class KuromojiUDF extends GenericUDF {
         try {
             responseCode = conn.getResponseCode();
         } catch (IOException e) {
-            throw new UDFArgumentException("Failed to get response code: " + 
e);
+            throw new UDFArgumentException("Failed to get response code: " + 
userDictURL + '\n'
+                    + ExceptionUtils.prettyPrintStackTrace(e));
         }
         if (responseCode != 200) {
             throw new UDFArgumentException("Got invalid response code: " + 
responseCode);
@@ -255,17 +259,19 @@ public final class KuromojiUDF extends GenericUDF {
 
         final InputStream is;
         try {
-            is = 
IOUtils.decodeInputStream(HttpUtils.getLimitedInputStream(conn,
-                MAX_INPUT_STREAM_SIZE));
+            is = IOUtils.decodeInputStream(
+                HttpUtils.getLimitedInputStream(conn, MAX_INPUT_STREAM_SIZE));
         } catch (NullPointerException | IOException e) {
-            throw new UDFArgumentException("Failed to get input stream from 
the connection: " + e);
+            throw new UDFArgumentException("Failed to get input stream from 
the connection: "
+                    + userDictURL + '\n' + 
ExceptionUtils.prettyPrintStackTrace(e));
         }
 
         final Reader reader = new InputStreamReader(is);
         try {
             return UserDictionary.open(reader); // return null if empty
         } catch (Throwable e) {
-            throw new UDFArgumentException("Failed to parse the file in CSV 
format: " + e);
+            throw new UDFArgumentException("Failed to parse the file in CSV 
format: " + userDictURL
+                    + '\n' + ExceptionUtils.prettyPrintStackTrace(e));
         }
     }
 

Reply via email to