How to insert response size and time into the page itself, at least partially?

前端 未结 3 1368
抹茶落季
抹茶落季 2020-12-02 21:41

I realize it\'s a chicken and egg problem and that it\'s not possible to accurately resolve the time it took to render a page (or the size of response) and insert that numbe

相关标签:
3条回答
  • 2020-12-02 22:00

    Or have an asynch Javascript call that gets the response time and size from the server after its ready? Treat it like a callback to be performed after the page is done loading and the values are ready to insert.

    0 讨论(0)
  • 2020-12-02 22:10

    This is a perfect use case for the Apache Commons IO CountingOutputStream. You need to create a Filter which uses HttpServletResponseWrapper to replace the OutputStream of the response with this one and replaces the Writer as well which should wrap the wrapped OutputStream. Then get hold of the HttpServletResponseWrapper instance in the request scope so that you can get the getByteCount() from the CountingOutputStream.

    Here's a kickoff example of the CountingFilter:

    public class CountingFilter implements Filter {
    
        @Override
        public void init(FilterConfig arg0) throws ServletException {
            // NOOP.
        }
    
        @Override
        public void doFilter(ServletRequest request, final ServletResponse response, FilterChain chain) throws IOException, ServletException {
            HttpServletResponse httpres = (HttpServletResponse) response;
            CountingServletResponse counter = new CountingServletResponse(httpres);
            HttpServletRequest httpreq = (HttpServletRequest) request;
            httpreq.setAttribute("counter", counter);
            chain.doFilter(request, counter);
            counter.flushBuffer(); // Push the last bits containing HTML comment.
        }
    
        @Override
        public void destroy() {
            // NOOP.
        }
    
    }
    

    The CountingServletResponse:

    public class CountingServletResponse extends HttpServletResponseWrapper {
    
        private final long startTime;
        private final CountingServletOutputStream output;
        private final PrintWriter writer;
    
        public CountingServletResponse(HttpServletResponse response) throws IOException {
            super(response);
            startTime = System.nanoTime();
            output = new CountingServletOutputStream(response.getOutputStream());
            writer = new PrintWriter(output, true);
        }
    
        @Override
        public ServletOutputStream getOutputStream() throws IOException {
            return output;
        }
    
        @Override
        public PrintWriter getWriter() throws IOException {
            return writer;
        }
    
        @Override
        public void flushBuffer() throws IOException {
            writer.flush();
        }
    
        public long getElapsedTime() {
            return System.nanoTime() - startTime;
        }
    
        public long getByteCount() throws IOException {
            flushBuffer(); // Ensure that all bytes are written at this point.
            return output.getByteCount();
        }
    
    }
    

    The CountingServletOutputStream:

    public class CountingServletOutputStream extends ServletOutputStream {
    
        private final CountingOutputStream output;
    
        public CountingServletOutputStream(ServletOutputStream output) {
            this.output = new CountingOutputStream(output);
        }
    
        @Override
        public void write(int b) throws IOException {
            output.write(b);
        }
    
        @Override
        public void flush() throws IOException {
            output.flush();
        }
    
        public long getByteCount() {
            return output.getByteCount();
        }
    
    }
    

    You can use it in any (even non-JSF) page as follows:

    <!DOCTYPE html>
    <html 
        xmlns="http://www.w3.org/1999/xhtml" 
        xmlns:h="http://java.sun.com/jsf/html">
        <h:head>
            <title>Counting demo</title>
        </h:head>
        <h:body>
            <h1>Hello World</h1>
        </h:body>
    </html>
    <!-- page size: #{counter.byteCount / 1000}KB -->
    <!-- render time: #{counter.elapsedTime / 1000000}ms -->
    
    0 讨论(0)
  • 2020-12-02 22:20

    I wrote a blog post explaining how you could create an Interceptor that would measure each method call your seam compontents where using.

    You can find the blog post here. You need to scroll down to the second part.

    Basically, all you need to do is annotate the method you want to measure with @MeasureCalls and it will automatically be picked up by the interceptor

    @Name("fooBean")
    @MeasureCalls
    public class FooBean
    

    An output would be something like this, showing the time it took in milliseconds and how many times each method was called:

    284.94 ms   1   FooBean.getRandomDroplets()
    284.56 ms   1   GahBean.getRandomDroplets()
    201.60 ms   2   SohBean.searchRatedDoodlesWithinHead()
    185.94 ms   1   FroBean.doSearchPopular()
    157.63 ms   1   FroBean.doSearchRecent()
     42.34 ms   1   FooBean.fetchMostRecentYodel()
     41.94 ms   1   GahBean.getMostRecentYodel()
     15.89 ms   1   FooBean.getNoOfYodels()
     15.00 ms   1   GahBean.getNoOfYodels()
      9.14 ms   1   SohBean.mainYodels()
      1.11 ms   2   SohBean.trackHoorayEvent()
      0.32 ms   1   FroBean.reset()
      0.22 ms  43   NohBean.thumbPicture()
      0.03 ms  18   FooBean.getMostRecentYodels()
      0.01 ms   1   NohBean.profilePicture()
      0.01 ms   1   FroBean.setToDefault()
      0.01 ms   1   FroBean.getRecentMarker() 
    
    0 讨论(0)
提交回复
热议问题