Revision: 8418
Author: [email protected]
Date: Mon Jul 26 15:35:20 2010
Log: Add basic logging to Scaffold app

Review at http://gwt-code-reviews.appspot.com/651803

Review by: [email protected]
http://code.google.com/p/google-web-toolkit/source/detail?r=8418

Added:
/trunk/user/src/com/google/gwt/requestfactory/client/RequestFactoryLogHandler.java
 /trunk/user/src/com/google/gwt/requestfactory/server/Logging.java
 /trunk/user/src/com/google/gwt/requestfactory/shared/LoggingRequest.java
Modified:
 /trunk/bikeshed/src/com/google/gwt/sample/expenses/gwt/Scaffold.gwt.xml
/trunk/user/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java /trunk/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java
 /trunk/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java

=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/requestfactory/client/RequestFactoryLogHandler.java Mon Jul 26 15:35:20 2010
@@ -0,0 +1,103 @@
+/*
+ * 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.requestfactory.client;
+
+import com.google.gwt.requestfactory.shared.Receiver;
+import com.google.gwt.requestfactory.shared.RequestFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * A Handler that does Remote Logging for applications using Request Factory
+ */
+public class RequestFactoryLogHandler extends Handler {
+  class LoggingReceiver implements Receiver<Long> {
+    @Override
+    public void onSuccess(Long response) {
+      if (response > 0) {
+        logger.finest("Remote logging successful");
+      } else {
+        logger.finest("Remote logging failed");
+      }
+    }
+  }
+
+  private static Logger logger =
+    Logger.getLogger(RequestFactoryLogHandler.class.getName());
+
+  private boolean closed;
+  private List<LogRecord> records;
+  private RequestFactory requestFactory;
+
+  public RequestFactoryLogHandler(RequestFactory requestFactory) {
+    this(requestFactory, Level.INFO);
+  }
+
+  /**
+   * Since records from this handler go accross the wire, it should only be
+ * used for important messages, and it's Level will often be higher than the
+   * Level being used app-wide.
+ * Do not set the level of this handler below FINER messages, since it logs
+   * messages at that level to acknowledge success/failure, and would cause
+   * an infinite loop.
+   */
+ public RequestFactoryLogHandler(RequestFactory requestFactory, Level level) {
+    this.requestFactory = requestFactory;
+    closed = false;
+    records = new ArrayList<LogRecord>();
+    setLevel(level);
+  }
+
+  @Override
+  public void close() {
+    flush();
+    closed = true;
+  }
+
+  @Override
+  public void flush() {
+    if (!closed) {
+      // We go ahead and just send a request for every message. The request
+      // factory will take care of the batching for us. Once we can send
+ // something more complex than Strings to the logMessage function, then
+      // we can do batching here.
+      for (LogRecord record : records) {
+        Receiver loggingReciever = new LoggingReceiver();
+        requestFactory.loggingRequest().logMessage(
+            record.getLevel().toString(),
+            record.getLoggerName(),
+            record.getMessage()).to(loggingReciever).fire();
+      }
+    }
+  }
+
+  @Override
+  public void publish(LogRecord record) {
+    if (!closed && isLoggable(record)) {
+      records.add(record);
+ // For now, just flush every time since a new request is sent for every
+      // record anyway.
+      flush();
+    }
+  }
+
+}
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/requestfactory/server/Logging.java Mon Jul 26 15:35:20 2010
@@ -0,0 +1,63 @@
+/*
+ * 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.requestfactory.server;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Server side object that handles log messages sent by
+ * {...@requestfactoryloghandler}
+ */
+public class Logging {
+  private static Logger logger = Logger.getLogger(Logging.class.getName());
+
+  public static Long logMessage(
+      String levelString, String loggerName, String originalMessage) {
+    Level level = Level.SEVERE;
+    try {
+      level = Level.parse(levelString);
+    } catch (IllegalArgumentException e) {
+      return 0L;
+    }
+    String message = String.format("Client Side Logger: %s Message: %s",
+        loggerName, originalMessage);
+
+    logger.log(level, message);
+    return 1L;
+  }
+
+  private Long id = 0L;
+  private Integer version = 0;
+
+  public Long getId() {
+    return this.id;
+  }
+
+  public Integer getVersion() {
+    return this.version;
+  }
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public void setVersion(Integer version) {
+    this.version = version;
+  }
+}
+
=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/requestfactory/shared/LoggingRequest.java Mon Jul 26 15:35:20 2010
@@ -0,0 +1,37 @@
+/*
+ * 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.requestfactory.shared;
+
+import com.google.gwt.requestfactory.server.Logging;
+
+/**
+ * "API Generated" request selector interface implemented by objects that give
+ * client access to the methods of {...@link Logging}.
+ * <p>
+ * IRL this class will be generated by a JPA-savvy tool run before compilation.
+ */
+...@service(Logging.class)
+public interface LoggingRequest {
+
+ // Should be returning something better than a Long, but that's all that is
+  // supported for now, so using it as a boolean.
+  // Should also be passing something better than a series of strings, but
+  // that's the only possibility for now.
+  RequestFactory.RequestObject<Long> logMessage(
+      String level, String loggerName, String message);
+
+}
=======================================
--- /trunk/bikeshed/src/com/google/gwt/sample/expenses/gwt/Scaffold.gwt.xml Fri May 28 08:44:36 2010 +++ /trunk/bikeshed/src/com/google/gwt/sample/expenses/gwt/Scaffold.gwt.xml Mon Jul 26 15:35:20 2010
@@ -18,7 +18,22 @@
 <module rename-to="scaffold">
   <inherits name="com.google.gwt.user.User" />
   <inherits name="com.google.gwt.user.theme.standard.Standard" />
+  <inherits name="com.google.gwt.logging.Logging"/>

   <inherits name="com.google.gwt.sample.expenses.gwt.ExpensesCommon" />
<entry-point class="com.google.gwt.sample.expenses.gwt.client.Scaffold" />
+
+  <!-- Logging Configuration -->
+ <!-- Right now, App Engine Dev Mode logging is borken for everything other
+       than the system handler, so only that one is enabled for now -->
+  <set-property name="gwt.logging.enabled" value="TRUE"/>
+  <set-property name="gwt.logging.logLevel" value="INFO"/>
+  <set-property name="gwt.logging.consoleHandler" value="DISABLED" />
+ <set-property name="gwt.logging.developmentModeHandler" value="DISABLED" />
+  <set-property name="gwt.logging.firebugHandler" value="DISABLED" />
+  <set-property name="gwt.logging.hasWidgetsHandler" value="DISABLED" />
+  <set-property name="gwt.logging.popupHandler" value="DISABLED" />
+  <set-property name="gwt.logging.systemHandler" value="ENABLED" />
+  <set-property name="gwt.logging.simpleRemoteHandler" value="DISABLED" />
+
 </module>
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java Fri Jul 23 10:49:57 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/client/impl/RequestFactoryJsonImpl.java Mon Jul 26 15:35:20 2010
@@ -22,11 +22,12 @@
 import com.google.gwt.http.client.RequestCallback;
 import com.google.gwt.http.client.RequestException;
 import com.google.gwt.http.client.Response;
+import com.google.gwt.requestfactory.client.RequestFactoryLogHandler;
 import com.google.gwt.requestfactory.shared.Receiver;
 import com.google.gwt.requestfactory.shared.RequestEvent;
+import com.google.gwt.requestfactory.shared.RequestEvent.State;
 import com.google.gwt.requestfactory.shared.RequestFactory;
 import com.google.gwt.requestfactory.shared.SyncRequest;
-import com.google.gwt.requestfactory.shared.RequestEvent.State;
 import com.google.gwt.requestfactory.shared.impl.RequestDataManager;
 import com.google.gwt.valuestore.client.DeltaValueStoreJsonImpl;
 import com.google.gwt.valuestore.client.ValueStoreJsonImpl;
@@ -35,6 +36,8 @@
 import com.google.gwt.valuestore.shared.impl.RecordToTypeMap;

 import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;

 /**
  * <p>
@@ -46,10 +49,15 @@
  */
 public abstract class RequestFactoryJsonImpl implements RequestFactory {

+  private static Logger logger =
+    Logger.getLogger(RequestFactory.class.getName());
+
+  private static String SERVER_ERROR = "Server Error";
+
   private HandlerManager handlerManager;

   private ValueStoreJsonImpl valueStore;
-
+
   public void fire(final RequestObject<?> requestObject) {
     RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,
         GWT.getHostPageBaseURL() + RequestFactory.URL);
@@ -58,16 +66,16 @@

       public void onError(Request request, Throwable exception) {
         postRequestEvent(State.RECEIVED, null);
-        // shell.error.setInnerText(SERVER_ERROR);
+        logger.log(Level.SEVERE, SERVER_ERROR, exception);
       }

       public void onResponseReceived(Request request, Response response) {
+        logger.finest("Response received");
         if (200 == response.getStatusCode()) {
           String text = response.getText();
           requestObject.handleResponseText(text);
         } else {
-          // shell.error.setInnerText(SERVER_ERROR + " ("
-          // + response.getStatusText() + ")");
+ logger.severe(SERVER_ERROR + " (" + response.getStatusText() + ")");
         }
         postRequestEvent(State.RECEIVED, response);
       }
@@ -75,11 +83,11 @@
     });

     try {
+      logger.finest("Sending fire request");
       builder.send();
       postRequestEvent(State.SENT, null);
     } catch (RequestException e) {
-      // shell.error.setInnerText(SERVER_ERROR + " (" + e.getMessage() +
-      // ")");
+ logger.log(Level.SEVERE, SERVER_ERROR + " (" + e.getMessage() + ")", e);
     }
   }

@@ -106,27 +114,27 @@

           public void onError(Request request, Throwable exception) {
             postRequestEvent(State.RECEIVED, null);
-            // shell.error.setInnerText(SERVER_ERROR);
+            logger.log(Level.SEVERE, SERVER_ERROR, exception);
           }

public void onResponseReceived(Request request, Response response) {
+            logger.finest("Response received");
             if (200 == response.getStatusCode()) {
               // parse the return value.
               receiver.onSuccess(jsonDeltas.commit(response.getText()));
             } else {
-              // shell.error.setInnerText(SERVER_ERROR + " ("
-              // + response.getStatusText() + ")");
+ logger.severe(SERVER_ERROR + " (" + response.getStatusText() + ")");
             }
             postRequestEvent(State.RECEIVED, response);
           }
         });

         try {
+          logger.finest("Sending sync request");
           builder.send();
           postRequestEvent(State.SENT, null);
         } catch (RequestException e) {
- // shell.error.setInnerText(SERVER_ERROR + " (" + e.getMessage() +
-          // ")");
+ logger.log(Level.SEVERE, SERVER_ERROR + " (" + e.getMessage() + ")", e);
         }
       }

@@ -143,6 +151,16 @@
   protected void init(HandlerManager handlerManager, RecordToTypeMap map) {
     this.valueStore = new ValueStoreJsonImpl(handlerManager, map);
     this.handlerManager = handlerManager;
+ // This Handler should really get added to the Root Logger here, but until + // App Engine Dev Mode logging is fixed, we can't use client side handlers + // on the Root Logger. Instead, just add it to our own logger as a proof of + // concept, and then log a Severe message to it to prove that it's working + // All the "finest" messages that this class normally logs are not logged
+    // to this handler since it would cause an infinite loop.
+ // TODO(unnurg): Once this is all set up, ensure that the severe messages
+    // in this class do not cause infinite loops during legitimate errors.
+    logger.addHandler(new RequestFactoryLogHandler(this));
+    logger.severe("Successful initialization!");
   }

   private void postRequestEvent(State received, Response response) {
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java Fri Jul 23 15:42:40 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/rebind/RequestFactoryGenerator.java Mon Jul 26 15:35:20 2010
@@ -267,6 +267,17 @@
       }
       requestSelectors.add(method);
     }
+
+ // In addition to the request selectors in the generated interface, there
+    // are a few which are in RequestFactory which also need to have
+ // implementations generated. Hard coding the addition of these here for now
+    JClassType t = generatorContext.getTypeOracle().findType(
+        RequestFactory.class.getName());
+    try {
+      requestSelectors.add(t.getMethod("loggingRequest", new JType[0]));
+    } catch (NotFoundException e) {
+      e.printStackTrace();
+    }

     // write init()
JClassType recordToTypeInterface = generatorContext.getTypeOracle().findType(
@@ -368,8 +379,8 @@
         packageName, implName);
     f.addImport(ClientRequestHelper.class.getName());
     f.addImport(RequestDataManager.class.getName());
-
-    f.addImplementedInterface(selectorInterface.getName());
+    f.addImport(mainType.getQualifiedSourceName() + "Impl");
+    f.addImplementedInterface(selectorInterface.getQualifiedSourceName());

     SourceWriter sw = f.createSourceWriter(generatorContext, out);
     sw.println();
=======================================
--- /trunk/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java Thu Jun 24 14:48:00 2010 +++ /trunk/user/src/com/google/gwt/requestfactory/shared/RequestFactory.java Mon Jul 26 15:35:20 2010
@@ -91,5 +91,13 @@

   void init(HandlerManager eventBus);

+ // The following methods match the format for the generated sub-interfaces + // and implementations are generated using the same code we use to generate
+  // those. In order to ensure this happens, each of the request selectors
+  // needs to be manually added to the requestSelectors list in
+  // RequestFactoryGenerator.java
+  LoggingRequest loggingRequest();
+
   SyncRequest syncRequest(DeltaValueStore deltaValueStore);
-}
+
+}

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to