Add stack trace display to the rest of the log handlers in dev mode
Review at http://gwt-code-reviews.appspot.com/861801
Review by: fredsa@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8773 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/logging/client/ConsoleLogHandler.java b/user/src/com/google/gwt/logging/client/ConsoleLogHandler.java
index c8a1853..e522f79 100644
--- a/user/src/com/google/gwt/logging/client/ConsoleLogHandler.java
+++ b/user/src/com/google/gwt/logging/client/ConsoleLogHandler.java
@@ -29,7 +29,7 @@
public class ConsoleLogHandler extends Handler {
public ConsoleLogHandler() {
- setFormatter(new TextLogFormatter());
+ setFormatter(new TextLogFormatter(true));
setLevel(Level.ALL);
}
diff --git a/user/src/com/google/gwt/logging/client/DevelopmentModeLogHandler.java b/user/src/com/google/gwt/logging/client/DevelopmentModeLogHandler.java
index 613ab04..c180499 100644
--- a/user/src/com/google/gwt/logging/client/DevelopmentModeLogHandler.java
+++ b/user/src/com/google/gwt/logging/client/DevelopmentModeLogHandler.java
@@ -29,7 +29,7 @@
public class DevelopmentModeLogHandler extends Handler {
public DevelopmentModeLogHandler() {
- setFormatter(new TextLogFormatter());
+ setFormatter(new TextLogFormatter(false));
setLevel(Level.ALL);
}
diff --git a/user/src/com/google/gwt/logging/client/FirebugLogHandler.java b/user/src/com/google/gwt/logging/client/FirebugLogHandler.java
index 9e84c51..7b5da6f 100644
--- a/user/src/com/google/gwt/logging/client/FirebugLogHandler.java
+++ b/user/src/com/google/gwt/logging/client/FirebugLogHandler.java
@@ -28,7 +28,7 @@
public class FirebugLogHandler extends Handler {
public FirebugLogHandler() {
- setFormatter(new TextLogFormatter());
+ setFormatter(new TextLogFormatter(true));
setLevel(Level.ALL);
}
diff --git a/user/src/com/google/gwt/logging/client/HasWidgetsLogHandler.java b/user/src/com/google/gwt/logging/client/HasWidgetsLogHandler.java
index 7e6d062..f2fec42 100644
--- a/user/src/com/google/gwt/logging/client/HasWidgetsLogHandler.java
+++ b/user/src/com/google/gwt/logging/client/HasWidgetsLogHandler.java
@@ -37,7 +37,7 @@
public HasWidgetsLogHandler(HasWidgets container) {
this.widgetContainer = container;
- setFormatter(new HtmlLogFormatter());
+ setFormatter(new HtmlLogFormatter(true));
setLevel(Level.ALL);
}
diff --git a/user/src/com/google/gwt/logging/client/HtmlLogFormatter.java b/user/src/com/google/gwt/logging/client/HtmlLogFormatter.java
index b6012b5..62f222f 100644
--- a/user/src/com/google/gwt/logging/client/HtmlLogFormatter.java
+++ b/user/src/com/google/gwt/logging/client/HtmlLogFormatter.java
@@ -16,8 +16,9 @@
package com.google.gwt.logging.client;
+import com.google.gwt.logging.impl.FormatterImpl;
+
import java.util.Date;
-import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
@@ -26,13 +27,25 @@
* and GetHtmlSuffix methods rather than format to ensure that the message
* is properly escaped.
*/
-public class HtmlLogFormatter extends Formatter {
+public class HtmlLogFormatter extends FormatterImpl {
+ private static String newline = "__GWT_LOG_FORMATTER_BR__";
+ private boolean showStackTraces;
+
+ public HtmlLogFormatter(boolean showStackTraces) {
+ this.showStackTraces = showStackTraces;
+ }
// TODO(unnurg): Handle the outputting of Throwables.
@Override
public String format(LogRecord event) {
StringBuilder html = new StringBuilder(getHtmlPrefix(event));
- html.append(getEscapedMessage(event));
+ html.append(getHtmlPrefix(event));
+ html.append(getRecordInfo(event, " "));
+ html.append(getEscaped(event.getMessage()));
+ if (showStackTraces) {
+ html.append(getEscaped(getStackTraceAsString(
+ event.getThrown(), newline, " ")));
+ }
html.append(getHtmlSuffix(event));
return html.toString();
}
@@ -44,17 +57,10 @@
prefix.append(getColor(event.getLevel().intValue()));
prefix.append("'>");
prefix.append("<code>");
- prefix.append(date.toString());
- prefix.append(" ");
- prefix.append(event.getLoggerName());
- prefix.append(" ");
- prefix.append(event.getLevel().getName());
- prefix.append(": ");
return prefix.toString();
}
protected String getHtmlSuffix(LogRecord event) {
- // TODO(unnurg): output throwables correctly
return "</code></span>";
}
@@ -86,11 +92,11 @@
return "#000"; // black
}
- // TODO(unnurg): There must be a cleaner way to do this...
- private String getEscapedMessage(LogRecord event) {
- String text = event.getMessage();
+ private String getEscaped(String text) {
text = text.replaceAll("<", "<");
text = text.replaceAll(">", ">");
+ // but allow the line breaks that we put in ourselves
+ text = text.replaceAll(newline, "<br>");
return text;
}
diff --git a/user/src/com/google/gwt/logging/client/SystemLogHandler.java b/user/src/com/google/gwt/logging/client/SystemLogHandler.java
index 428bbb9..12aeac8 100644
--- a/user/src/com/google/gwt/logging/client/SystemLogHandler.java
+++ b/user/src/com/google/gwt/logging/client/SystemLogHandler.java
@@ -28,7 +28,7 @@
public class SystemLogHandler extends Handler {
public SystemLogHandler() {
- setFormatter(new TextLogFormatter());
+ setFormatter(new TextLogFormatter(true));
setLevel(Level.ALL);
}
diff --git a/user/src/com/google/gwt/logging/client/TextLogFormatter.java b/user/src/com/google/gwt/logging/client/TextLogFormatter.java
index 1c01125..b001f7b 100644
--- a/user/src/com/google/gwt/logging/client/TextLogFormatter.java
+++ b/user/src/com/google/gwt/logging/client/TextLogFormatter.java
@@ -16,28 +16,27 @@
package com.google.gwt.logging.client;
-import java.util.Date;
-import java.util.logging.Formatter;
+import com.google.gwt.logging.impl.FormatterImpl;
+
import java.util.logging.LogRecord;
/**
* Formats LogRecords into 2 lines of text.
*/
-public class TextLogFormatter extends Formatter {
+public class TextLogFormatter extends FormatterImpl {
+ private boolean showStackTraces;
+
+ public TextLogFormatter(boolean showStackTraces) {
+ this.showStackTraces = showStackTraces;
+ }
@Override
public String format(LogRecord event) {
- Date date = new Date(event.getMillis());
StringBuilder message = new StringBuilder();
- message.append(date.toString());
- message.append(" ");
- message.append(event.getLoggerName());
- message.append("\n");
- message.append(event.getLevel().getName());
- message.append(": ");
+ message.append(getRecordInfo(event, "\n"));
message.append(event.getMessage());
- if (event.getThrown() != null) {
- // TODO(unnurg): output throwables correctly
+ if (showStackTraces) {
+ message.append(getStackTraceAsString(event.getThrown(), "\n", "\t"));
}
return message.toString();
}
diff --git a/user/src/com/google/gwt/logging/impl/FormatterImpl.java b/user/src/com/google/gwt/logging/impl/FormatterImpl.java
new file mode 100644
index 0000000..051f6f7
--- /dev/null
+++ b/user/src/com/google/gwt/logging/impl/FormatterImpl.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed 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 com.google.gwt.logging.impl;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.logging.Formatter;
+import java.util.logging.LogRecord;
+
+/**
+ * Base class for Formatters - provides common functionality
+ */
+public abstract class FormatterImpl extends Formatter {
+
+ /**
+ * Note that this format is likely to change in the future.
+ * Outputs the meta information in the log record in the following format:
+ * <pre>Date LoggerName\nLEVEL:</pre>
+ * Most formatters will append the message right after the colon
+ */
+ protected String getRecordInfo(LogRecord event, String newline) {
+ Date date = new Date(event.getMillis());
+ StringBuilder s = new StringBuilder();
+ s.append(date.toString());
+ s.append(" ");
+ s.append(event.getLoggerName());
+ s.append(newline);
+ s.append(event.getLevel().getName());
+ s.append(": ");
+ return s.toString();
+ }
+
+ // This method is borrowed from AbstractTreeLogger.
+ // TODO(unnurg): once there is a clear place where code used by gwt-dev and
+ // gwt-user can live, move this function there.
+ protected String getStackTraceAsString(Throwable e, String newline,
+ String indent) {
+ if (e == null) {
+ return "";
+ }
+ // For each cause, print the requested number of entries of its stack
+ // trace, being careful to avoid getting stuck in an infinite loop.
+ //
+ StringBuffer s = new StringBuffer(newline);
+ Throwable currentCause = e;
+ String causedBy = "";
+ HashSet<Throwable> seenCauses = new HashSet<Throwable>();
+ while (currentCause != null && !seenCauses.contains(currentCause)) {
+ seenCauses.add(currentCause);
+ s.append(causedBy);
+ causedBy = newline + "Caused by: "; // after 1st, all say "caused by"
+ s.append(currentCause.getClass().getName());
+ s.append(": " + currentCause.getMessage());
+ StackTraceElement[] stackElems = currentCause.getStackTrace();
+ if (stackElems != null) {
+ for (int i = 0; i < stackElems.length; ++i) {
+ s.append(newline + indent + "at ");
+ s.append(stackElems[i].toString());
+ }
+ }
+
+ currentCause = currentCause.getCause();
+ }
+ return s.toString();
+ }
+
+}