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)); } }
