Как вставить размер и время ответа в саму страницу, хотя бы частично? - программирование
Подтвердить что ты не робот

Как вставить размер и время ответа в саму страницу, хотя бы частично?

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

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

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

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

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

Спасибо,
-A

4b9b3361

Ответ 1

Это идеальный вариант использования 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

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

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

В принципе, все, что вам нужно сделать, это аннотировать метод, который вы хотите измерить с помощью @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() 

Ответ 3

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