Как вставить размер и время ответа в саму страницу, хотя бы частично? - PullRequest
13 голосов
/ 11 июля 2010

Я понимаю, что это проблема курицы и яйца, и невозможно точно определить время, необходимое для отображения страницы (или размер ответа), и вставить это число в саму страницу, не затрагивая ни один из показателей.Тем не менее, я ищу способ частично вставить любой номер на странице приложения JSF / Facelets / Seam.

Например, внизу страницы .jsf где-то:

<!-- page size: 10.3Kb -->
<!-- render time: 0.2s -->

Я сталкивался с JSFUnit JSFTimer , который действительно удобен.Однако подход с прослушиванием фаз не позволяет вставлять результаты фазы RENDER_RESPONSE на страницу.Также не уверен, как получить доступ к размеру закодированного ответа.

Существует ли быстрый и грязный способ подключиться к какому-либо событию постобработки в конце или после окончания RENDER_RESPONSE и ввести обаномера на странице, которая будет отображаться?Один из способов достижения этого, возможно, через фильтры сервлетов, но я ищу что-то более простое;возможно трюк с Швом или Facelets ...

Спасибо,
-A

Ответы [ 3 ]

22 голосов
/ 11 июля 2010

Это идеальный вариант использования для Apache Commons IO CountingOutputStream.Вам нужно создать Filter, который использует HttpServletResponseWrapper, чтобы заменить OutputStream ответа этим, а также заменит Writer, который должен обернуть OutputStream.Затем возьмите экземпляр HttpServletResponseWrapper в области запроса, чтобы вы могли получить getByteCount() из CountingOutputStream.

Вот начальный пример 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.
    }

}

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();
    }

}

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();
    }

}

Вы можете использовать его на любой (даже не JSF) странице следующим образом:

<!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 -->
2 голосов
/ 21 января 2011

Я написал сообщение в блоге, объясняющее, как можно создать перехватчик, который будет измерять каждый метод, вызывающий ваши компоненты шва, где используется.

Вы можете найти сообщение в блоге здесь .Вам нужно прокрутить вниз до второй части.

По сути, все, что вам нужно сделать, это аннотировать метод, который вы хотите измерить с помощью @MeasureCalls, и он будет автоматически получен перехватчиком

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

Вывод будет выглядеть примерно такэто, показывая время, которое заняло в миллисекундах и сколько раз каждый метод был вызван:

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 голосов
/ 11 июля 2010

Или есть асинхронный вызов Javascript, который получает время и размер ответа от сервера после его готовности? Рассматривайте это как обратный вызов, который будет выполнен после загрузки страницы и готовности значений для вставки.

...