]> source.dussan.org Git - vaadin-framework.git/commitdiff
Implemented #8694 - API providing profiling info for TestBench 3.x
authorJonatan Kronqvist <jonatan.kronqvist@itmill.com>
Thu, 19 Apr 2012 06:33:34 +0000 (06:33 +0000)
committerJonatan Kronqvist <jonatan.kronqvist@itmill.com>
Thu, 19 Apr 2012 06:33:34 +0000 (06:33 +0000)
svn changeset:23582/svn branch:6.8

src/com/vaadin/terminal/gwt/client/ApplicationConnection.java
src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java
src/com/vaadin/terminal/gwt/server/AbstractApplicationServlet.java
src/com/vaadin/terminal/gwt/server/AbstractCommunicationManager.java
src/com/vaadin/terminal/gwt/server/RequestTimer.java [new file with mode: 0644]

index 7a3a28495afdf71afd3d0783907ab4cb522ebfeb..93e2657eb41af8544e5c49efc9d6d6bc39b3af4e 100644 (file)
@@ -224,12 +224,22 @@ public class ApplicationConnection {
                return ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::hasActiveRequest()()
                                || ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::isExecutingDeferredCommands()();
        }
+       
        var vi = ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::getVersionInfo()();
        if (vi) {
                client.getVersionInfo = function() {
                        return vi;
                }
        }
+       
+       client.getProfilingData = function() {
+           var pd = [
+                   ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::lastProcessingTime,
+                    ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::totalProcessingTime
+               ];
+           pd = pd.concat(ap.@com.vaadin.terminal.gwt.client.ApplicationConnection::testBenchServerStatus);
+           return pd;
+       }
 
        client.getElementByPath = function(id) {
                return componentLocator.@com.vaadin.terminal.gwt.client.ComponentLocator::getElementByPath(Ljava/lang/String;)(id);
@@ -632,6 +642,13 @@ public class ApplicationConnection {
     }
 
     int cssWaits = 0;
+
+    protected int lastProcessingTime;
+
+    protected int totalProcessingTime;
+
+    private ValueMap testBenchServerStatus;
+
     static final int MAX_CSS_WAITS = 100;
 
     protected void handleWhenCSSLoaded(final String jsonText,
@@ -952,6 +969,13 @@ public class ApplicationConnection {
                     json.getValueMap("typeMappings"), widgetSet);
         }
 
+        /*
+         * Hook for TestBench to get details about server status
+         */
+        if (json.containsKey("tbss")) {
+            testBenchServerStatus = json.getValueMap("tbss");
+        }
+
         Command c = new Command() {
             public void execute() {
                 VConsole.dirUIDL(json, configuration);
@@ -1129,10 +1153,12 @@ public class ApplicationConnection {
 
                 // TODO build profiling for widget impl loading time
 
-                final long prosessingTime = (new Date().getTime())
-                        - start.getTime();
+                lastProcessingTime = (int) ((new Date().getTime()) - start
+                        .getTime());
+                totalProcessingTime += lastProcessingTime;
+
                 VConsole.log(" Processing time was "
-                        + String.valueOf(prosessingTime) + "ms for "
+                        + String.valueOf(lastProcessingTime) + "ms for "
                         + jsonText.length() + " characters of JSON");
                 VConsole.log("Referenced paintables: "
                         + idToPaintableDetail.size());
index acae039e8ba680cc4e876134fed1dc1da6027e50..a5923cb47f429b2a51135467d6a3e38ccfa40425 100644 (file)
@@ -326,6 +326,11 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
 
     protected void handleRequest(PortletRequest request,
             PortletResponse response) throws PortletException, IOException {
+        RequestTimer.RequestWrapper wrappedRequest = new RequestTimer.RequestWrapper(
+                request);
+        RequestTimer requestTimer = RequestTimer.get(wrappedRequest);
+        requestTimer.start(wrappedRequest);
+
         RequestType requestType = getRequestType(request);
 
         if (requestType == RequestType.UNKNOWN) {
@@ -490,6 +495,9 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet
                                 request, response);
 
                     }
+
+                    requestTimer.stop();
+                    RequestTimer.set(wrappedRequest, requestTimer);
                 }
             }
         }
index 13082cf1aa328a1230a5a4addf3225b1dd66ff5d..04ea423004783f4ad4a3565db91c05e3ab877a1d 100644 (file)
@@ -401,6 +401,10 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
     @Override
     protected void service(HttpServletRequest request,
             HttpServletResponse response) throws ServletException, IOException {
+        RequestTimer.RequestWrapper wrappedRequest = new RequestTimer.RequestWrapper(
+                request);
+        RequestTimer requestTimer = RequestTimer.get(wrappedRequest);
+        requestTimer.start(wrappedRequest);
 
         RequestType requestType = getRequestType(request);
         if (!ensureCookiesEnabled(requestType, request, response)) {
@@ -549,6 +553,8 @@ public abstract class AbstractApplicationServlet extends HttpServlet implements
                             request, response);
                 }
 
+                requestTimer.stop();
+                RequestTimer.set(wrappedRequest, requestTimer);
             }
 
         }
index c0654359a17b19de6aff18c8a42914016c2f337f..9a6bccebb81f14353b1ebad1f692d0a6b8787310 100644 (file)
@@ -912,7 +912,7 @@ public abstract class AbstractCommunicationManager implements
                 repaintAll = true;
             }
 
-            writeUidlResponce(callback, repaintAll, outWriter, window,
+            writeUidlResponse(request, callback, repaintAll, outWriter, window,
                     analyzeLayouts);
 
         }
@@ -922,9 +922,9 @@ public abstract class AbstractCommunicationManager implements
 
     }
 
-    public void writeUidlResponce(Callback callback, boolean repaintAll,
-            final PrintWriter outWriter, Window window, boolean analyzeLayouts)
-            throws PaintException {
+    public void writeUidlResponse(Request request, Callback callback,
+            boolean repaintAll, final PrintWriter outWriter, Window window,
+            boolean analyzeLayouts) throws PaintException {
         outWriter.print("\"changes\":[");
 
         ArrayList<Paintable> paintables = null;
@@ -1205,6 +1205,20 @@ public abstract class AbstractCommunicationManager implements
         if (dragAndDropService != null) {
             dragAndDropService.printJSONResponse(outWriter);
         }
+
+        writePerformanceDataForTestBench(request, outWriter);
+    }
+
+    /**
+     * Adds the performance timing data used by TestBench 3 to the UIDL
+     * response.
+     */
+    private void writePerformanceDataForTestBench(final Request request,
+            final PrintWriter outWriter) {
+        Long totalTime = (Long) request.getAttribute("TOTAL");
+        Long lastRequestTime = (Long) request.getAttribute("LASTREQUEST");
+        outWriter.write(String.format(", \"tbss\":[%d, %d]", totalTime,
+                lastRequestTime));
     }
 
     private int getTimeoutInterval() {
diff --git a/src/com/vaadin/terminal/gwt/server/RequestTimer.java b/src/com/vaadin/terminal/gwt/server/RequestTimer.java
new file mode 100644 (file)
index 0000000..3649ed3
--- /dev/null
@@ -0,0 +1,138 @@
+package com.vaadin.terminal.gwt.server;
+
+import javax.portlet.PortletRequest;
+import javax.portlet.PortletSession;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+/**
+ * Times the handling of requests and stores the information as an attribute in
+ * the request. The timing info is later passed on to the client in the UIDL and
+ * the client provides JavaScript API for accessing this data from e.g.
+ * TestBench.
+ * 
+ * @author Jonatan Kronqvist / Vaadin Ltd
+ */
+public class RequestTimer {
+    public static final String SESSION_ATTR_ID = "REQUESTTIMER";
+
+    private long requestStartTime = 0;
+    private long totalSessionTime = 0;
+    private long lastRequestTime = -1;
+
+    /**
+     * This class acts as a proxy for setting and getting session and request
+     * attributes on HttpServletRequests and PortletRequests. Using this class
+     * we don't need to duplicate code everywhere.
+     */
+    static class RequestWrapper {
+        private final HttpServletRequest servletRequest;
+        private final PortletRequest portletRequest;
+
+        public RequestWrapper(HttpServletRequest servletRequest) {
+            this.servletRequest = servletRequest;
+            portletRequest = null;
+        }
+
+        public RequestWrapper(PortletRequest portletRequest) {
+            this.portletRequest = portletRequest;
+            servletRequest = null;
+        }
+
+        public void setAttribute(String name, Object value) {
+            if (servletRequest != null) {
+                servletRequest.setAttribute(name, value);
+            } else {
+                portletRequest.setAttribute(name, value);
+            }
+        }
+
+        public void setSessionAttribute(String name, Object value) {
+            if (servletRequest != null) {
+                HttpSession session = servletRequest.getSession();
+                if (session != null) {
+                    session.setAttribute(name, value);
+                }
+            } else {
+                PortletSession portletSession = portletRequest
+                        .getPortletSession();
+                if (portletSession != null) {
+                    portletSession.setAttribute(name, value);
+                }
+            }
+        }
+
+        public Object getSessionAttribute(String name) {
+            if (servletRequest != null) {
+                HttpSession session = servletRequest.getSession();
+                if (session != null) {
+                    return session.getAttribute(name);
+                }
+            } else {
+                PortletSession portletSession = portletRequest
+                        .getPortletSession();
+                if (portletSession != null) {
+                    return portletSession.getAttribute(name);
+                }
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Starts the timing of a request. This should be called before any
+     * processing of the request.
+     * 
+     * @param request
+     *            the request.
+     */
+    public void start(RequestWrapper request) {
+        requestStartTime = System.nanoTime();
+        request.setAttribute("TOTAL", totalSessionTime);
+        request.setAttribute("LASTREQUEST", lastRequestTime);
+    }
+
+    /**
+     * Stops the timing of a request. This should be called when all processing
+     * of a request has finished.
+     */
+    public void stop() {
+        // Measure and store the total handling time. This data can be
+        // used in TestBench 3 tests.
+        long time = (System.nanoTime() - requestStartTime) / 1000000;
+        lastRequestTime = time;
+        totalSessionTime += time;
+    }
+
+    /**
+     * Returns a valid request timer for the specified request. Timers are
+     * session bound.
+     * 
+     * @param request
+     *            the request for which to get a valid timer.
+     * @return a valid timer.
+     */
+    public static RequestTimer get(RequestWrapper request) {
+        RequestTimer timer = (RequestTimer) request
+                .getSessionAttribute(SESSION_ATTR_ID);
+        if (timer == null) {
+            timer = new RequestTimer();
+        }
+        return timer;
+    }
+
+    /**
+     * Associates the specified request timer with the specified request. Since
+     * {@link #get(RequestWrapper)} will, at one point or another, return a new
+     * instance, this method should be called to keep the request <-> timer
+     * association updated.
+     * 
+     * @param request
+     *            the request for which to set the timer.
+     * @param requestTimer
+     *            the timer.
+     */
+    public static void set(RequestWrapper request, RequestTimer requestTimer) {
+        request.setSessionAttribute(RequestTimer.SESSION_ATTR_ID, requestTimer);
+    }
+}