2012-11-20 15 views
6

Mi chiedo se posso usare un filtro (nel mio caso un CorsFilter) per misurare il tempo E per dedicare il tempo al messaggio stesso. So che il seguente funziona bene:Come utilizzare un filtro per misurare le prestazioni?

public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { 
    long startTime = System.nanoTime(); 
    chain.doFilter(request, response); 
    long endTime = System.nanoTime(); 
    System.out.println("Time: " + (endTime - startTime)); 
} 

Che ovviamente emette il tempo totale in secondi. Volevo inserire il tempo nell'intestazione della risposta restituita in modo che il destinatario potesse guardare l'intestazione e vedere quanto tempo ci voleva. Il seguente codice non funziona:

public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { 
    long startTime = System.nanoTime(); 
    if(response instanceof HttpServletResponse) { 
    HttpServletResponse httpResp = (HttpServletResponse)response; 
    httpResp.addHeader("Start-time", Long.toString(startTime)); 
    } 

    chain.doFilter(request, response); 
    long endTime = System.nanoTime(); 
    if(response instanceof HttpServletResponse) { 
    HttpServletResponse httpResp = (HttpServletResponse)response; 
    httpResp.addHeader("End-time", Long.toString(endTime)); 
    } 
} 

L'intestazione include solo ora di inizio e non di fine. Presumo che ciò sia dovuto al fatto che il messaggio è già stato inviato in modo che la modifica dell'oggetto non abbia alcun effetto.

Qualcuno ha una soluzione elegante/intelligente per inserire i tempi nell'intestazione tramite l'uso di un filtro?

Grazie, Phil

Aggiornamento

ho studiato l'uso di un HttpServletResponseWrapper per affrontare questa soluzione. Ciò non riesce ancora a produrre né XXX-EndTime né YYY-EndTime nell'intestazione della risposta.

@Override 
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException { 
    long startTime = System.nanoTime(); 

    if(response instanceof HttpServletResponse) { 
    HttpServletResponse httpResp = (HttpServletResponse)response; 
    httpResp.addHeader("Access-Control-Allow-Origin", "*"); 
    httpResp.addHeader("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS"); 
    httpResp.addHeader("Allow", "GET, HEAD, OPTIONS"); 
    httpResp.addHeader("Access-Control-Allow-Headers", "*"); 
    httpResp.addHeader("A-Runtime", Long.toString(startTime)); 
    } 

    OutputStream out = response.getOutputStream(); 

    GenericResponseWrapper wrapper = new GenericResponseWrapper((HttpServletResponse) response); 

    chain.doFilter(request,wrapper); 

    out.write(wrapper.getData()); 

    if(response instanceof HttpServletResponse) { 
HttpServletResponse httpResp = (HttpServletResponse)response; 
httpResp.addHeader("XXX-EndTime", Long.toString(System.nanoTime() - startTime)); 

    wrapper.addHeader("YYY-EndTime", Long.toString(System.nanoTime() - startTime)); 
    } 

    out.close(); 
} 

risposta

2

Dai uno sguardo allo HttpServletResponseWrapper.


Ok, quindi codice:

Questo codice tamponi l'uscita (in due modi) e quindi aggiungendo l'intestazione dopo le opere pseudo-uscita. In realtà addHeader avrebbe potuto essere implementato emettendo, quindi siamo fortunati funziona. Codice del caso limite. Se sfortunato, addHeader dovrebbe essere sovrascritto.

Mind, quando ho provato, solo getOutputStream è stato chiamato nella mia app di test. È possibile scegliere se scegliere getPrintWriter o getOutputStream.

private static class PostponingResponseWrapper extends HttpServletResponseWrapper { 

    private ByteArrayOutputStream bos; 
    private ServletOutputStream outputStream; 
    private StringWriter sw; 
    private PrintWriter printWriter; 
    private boolean usingOutputStream; 
    private boolean usingWriter; 

    public PostponingResponseWrapper (HttpServletResponse response) { 
     super(response); 
     bos = new ByteArrayOutputStream(); 
     outputStream = new ServletOutputStream() { 
      @Override 
      public void write(int b) throws IOException { 
       bos.write(b); 
      } 
     }; 
     sw = new StringWriter(); 
     printWriter = new PrintWriter(sw); 
    } 

    @Override 
    public PrintWriter getWriter() throws IOException { 
     usingWriter = true; 
     LOGGER.info("getWriter usingWriter {}, usingOutputStream {}", usingWriter, usingOutputStream); 
     return printWriter; 
    } 

    @Override 
    public void flushBuffer() throws IOException { 
     LOGGER.info("flushBuffer"); 
    } 

    @Override 
    public ServletOutputStream getOutputStream() throws IOException { 
     usingOutputStream = true; 
     LOGGER.info("getOutputStream usingWriter {}, usingOutputStream {}", usingWriter, usingOutputStream); 
     ServletOutputStream out = new ServletOutputStream() { 
      @Override 
      public void write(int b) throws IOException { 
       outputStream.write(b); 
      } 
     }; 
     return out; 
    } 

    public void finish() throws IOException { 
     LOGGER.info("finish"); 
     if (usingWriter) { 
      super.getWriter().print(sw.toString()); 
     } else if (usingOutputStream) { 
      super.getOutputStream().write(bos.toByteArray()); 
     } 
    } 
} 

public void doFilter(ServletRequest request, ServletResponse response, 
     FilterChain chain) throws IOException, ServletException { 
    HttpServletResponse httpServletResponse = (HttpServletResponse) response; 
    PostponingResponseWrapper responseWrapper = 
      new PostponingResponseWrapper (httpServletResponse); 
    responseWrapper.addHeader("Before", "Already-Worked"); 
    chain.doFilter(request, responseWrapper); 
    responseWrapper.addHeader("After", "And-Now-This"); 
    responseWrapper.finish(); // Writes the actual response 
} 
+2

-1 risposte lik questo apre più domande poi rispondono. – Yevgeniy

+0

@YevgeniyM. hai ragione, dovrebbe essere stato un commento, che esiste una classe wrapper +1. –

+0

Ok, ho implementato una soluzione usando HttpServletResponseWrapper ma ancora non riesco a farlo funzionare! Aggiornerò la domanda di cui sopra con il mio nuovo codice. – Phil

Problemi correlati