-On the server, when exceptions occur, pass back a traceback along with the other info
-On the client, added an expandable "error log" box at the bottom. When non-JSON responses are received, show the full response in the log.  When exceptions are received, show the traceback in the log.



git-svn-id: http://test.kernel.org/svn/autotest/trunk@1361 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/frontend/afe/json_rpc/serviceHandler.py b/frontend/afe/json_rpc/serviceHandler.py
index 1f6036c..93d8b6b 100644
--- a/frontend/afe/json_rpc/serviceHandler.py
+++ b/frontend/afe/json_rpc/serviceHandler.py
@@ -72,6 +72,7 @@
     
     def handleRequest(self, json):
         err=None
+        err_traceback = None
         result = None
         id_=''
 
@@ -95,16 +96,18 @@
             try:
                 meth = self.findServiceEndpoint(methName)
             except Exception, e:
-                traceback.print_exc()
+                err_traceback = traceback.format_exc()
+                print err_traceback
                 err = e
 
         if err == None:
             try:
                 result = self.invokeServiceEndpoint(meth, args)
             except Exception, e:
-                traceback.print_exc()
+                err_traceback = traceback.format_exc()
+                print err_traceback
                 err = e
-        resultdata = self.translateResult(result, err, id_)
+        resultdata = self.translateResult(result, err, err_traceback, id_)
 
         return resultdata
 
@@ -130,9 +133,10 @@
     def invokeServiceEndpoint(self, meth, args):
         return meth(*args)
 
-    def translateResult(self, rslt, err, id_):
+    def translateResult(self, rslt, err, err_traceback, id_):
         if err != None:
-            err = {"name": err.__class__.__name__, "message":str(err)}
+            err = {"name": err.__class__.__name__, "message":str(err),
+                   "traceback": err_traceback}
             rslt = None
 
         try:
diff --git a/frontend/client/src/afeclient/client/ClientMain.java b/frontend/client/src/afeclient/client/ClientMain.java
index bd5285c..5f7b459 100644
--- a/frontend/client/src/afeclient/client/ClientMain.java
+++ b/frontend/client/src/afeclient/client/ClientMain.java
@@ -29,6 +29,8 @@
     public void onModuleLoad() {
         JsonRpcProxy.getProxy().setUrl(RPC_URL);
         
+        NotifyManager.getInstance().initialize();
+        
         // initialize static data, and don't show main UI until that's done
         StaticDataRepository.getRepository().refresh(
                                  new StaticDataRepository.FinishedCallback() {
@@ -36,8 +38,6 @@
                 finishLoading();
             }
         });
-        
-        NotifyManager.getInstance().initialize();
     }
     
     protected void finishLoading() {
diff --git a/frontend/client/src/afeclient/client/JsonRpcCallback.java b/frontend/client/src/afeclient/client/JsonRpcCallback.java
index f0c0c92..26e242f 100644
--- a/frontend/client/src/afeclient/client/JsonRpcCallback.java
+++ b/frontend/client/src/afeclient/client/JsonRpcCallback.java
@@ -1,6 +1,7 @@
 package afeclient.client;
 
 import com.google.gwt.json.client.JSONObject;
+import com.google.gwt.json.client.JSONString;
 import com.google.gwt.json.client.JSONValue;
 
 abstract class JsonRpcCallback {
@@ -8,7 +9,11 @@
     public void onError(JSONObject errorObject) {
         String name = errorObject.get("name").isString().stringValue();
         String message = errorObject.get("message").isString().stringValue();
+        JSONString tracebackString = errorObject.get("traceback").isString();
+        String traceback = null;
+        if (tracebackString != null)
+            traceback = tracebackString.stringValue();
         String errorString =  name + ": " + message;
-        NotifyManager.getInstance().showError(errorString);
+        NotifyManager.getInstance().showError(errorString, traceback);
     }
 }
diff --git a/frontend/client/src/afeclient/client/JsonRpcProxy.java b/frontend/client/src/afeclient/client/JsonRpcProxy.java
index 93825a8..b90f552 100644
--- a/frontend/client/src/afeclient/client/JsonRpcProxy.java
+++ b/frontend/client/src/afeclient/client/JsonRpcProxy.java
@@ -84,26 +84,25 @@
                     responseValue = JSONParser.parse(responseText);
                 }
                 catch (JSONException exc) {
-                    notify.showError(exc.toString());
+                    notify.showError(exc.toString(), responseText);
                     return;
                 }
                 
                 JSONObject responseObject = responseValue.isObject();
-                JSONObject error = responseObject.get("error").isObject();
-                if (error != null) {
-                    callback.onError(error);
+                JSONValue error = responseObject.get("error");
+                if (error == null) {
+                    notify.showError("Bad JSON response", responseText);
+                    return;
+                }
+                else if (error.isObject() != null) {
+                    callback.onError(error.isObject());
                     return;
                 }
 
                 JSONValue result = responseObject.get("result");
                 callback.onSuccess(result);
-
-                // Element error_iframe =
-                // DOM.getElementById("error_iframe");
-                // DOM.setInnerHTML(error_iframe,
-                // responseText);
-                }
-            });
+            }
+        });
         return success;
     }
 }
diff --git a/frontend/client/src/afeclient/client/NotifyManager.java b/frontend/client/src/afeclient/client/NotifyManager.java
index 3663101..23c1cba 100644
--- a/frontend/client/src/afeclient/client/NotifyManager.java
+++ b/frontend/client/src/afeclient/client/NotifyManager.java
@@ -1,7 +1,11 @@
 package afeclient.client;
 
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.DisclosurePanel;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.RootPanel;
+import com.google.gwt.user.client.ui.TextArea;
 
 /**
  * A singleton class to manage popup notifications, including error messages and
@@ -40,9 +44,32 @@
         }
     }
     
+    class ErrorLog extends Composite {
+        protected DisclosurePanel disclosurePanel = 
+            new DisclosurePanel("Error log");
+        protected TextArea errorTextArea = new TextArea();
+        
+        public ErrorLog() {
+            errorTextArea.setCharacterWidth(120);
+            errorTextArea.setVisibleLines(30);
+            errorTextArea.setReadOnly(true);
+            disclosurePanel.add(errorTextArea);
+            initWidget(disclosurePanel);
+        }
+        
+        public void logError(String error) {
+            String errorText = errorTextArea.getText();
+            if (!errorText.equals(""))
+                errorText += "\n------------------------------\n";
+            errorText += error;
+            errorTextArea.setText(errorText);
+        }
+    }
+    
     protected NotifyBox errorNotify = new NotifyBox(true);
     protected NotifyBox messageNotify = new NotifyBox(true);
     protected NotifyBox loadingNotify = new NotifyBox(false);
+    protected ErrorLog errorLog = new ErrorLog();
     
     private NotifyManager() {
         errorNotify.addStyle("error");
@@ -54,6 +81,9 @@
     public void initialize() {
         errorNotify.hide();
         messageNotify.hide();
+        
+        RootPanel.get("error_log").add(errorLog);
+        errorLog.setVisible(false);
     }
     
     public static NotifyManager getInstance() {
@@ -63,8 +93,17 @@
     /**
      * Show an error message.
      */
-    public void showError(String error) {
+    public void showError(String error, String logMessage) {
+        String errorLogText = error;
+        if (logMessage != null)
+            errorLogText += "\n" + logMessage; 
         errorNotify.showMessage(error);
+        errorLog.logError(errorLogText);
+        errorLog.setVisible(true);
+    }
+    
+    public void showError(String error) {
+        showError(error, null);
     }
     
     /**
diff --git a/frontend/client/src/afeclient/public/ClientMain.html b/frontend/client/src/afeclient/public/ClientMain.html
index 09aaf94..7128376 100644
--- a/frontend/client/src/afeclient/public/ClientMain.html
+++ b/frontend/client/src/afeclient/public/ClientMain.html
@@ -111,6 +111,8 @@
         <div id="hosts_list"></div>
       </div>
     </div>
+    <br>
+    <div id="error_log"></div>
     
     <!--  for debugging only -->
     <div id="error_display"></div>
diff --git a/frontend/client/src/afeclient/public/afeclient.css b/frontend/client/src/afeclient/public/afeclient.css
index 7534f26..17c5e5d 100644
--- a/frontend/client/src/afeclient/public/afeclient.css
+++ b/frontend/client/src/afeclient/public/afeclient.css
@@ -168,6 +168,7 @@
 
 .error {
   color: red;
+  white-space: pre;
 }
 
 .gwt-TextArea {