2010-09-07 16 views
3

我有什麼選項來分析春天mvc應用程序中的頁面請求?如何配置一個春天mvc應用程序的頁面請求

我想要得到的頁面請求花費的時間,與各階段喜歡它需要多長時間來呈現Freemarker模板一起崩潰,休眠DB調用等

+0

對於負載和性能測試,我建議看看http://jmeter.apache.org/ – Jack 2015-05-29 05:18:13

回答

3

我們剛剛完成用一個攔截器和一個自定義標籤類似的東西。該解決方案足夠輕以便在生產環境中使用,在響應底部將其數據顯示爲HTML註釋,並允許您選擇帶有請求參數的更詳細的日誌記錄。將下面的攔截器應用於要配置的所有請求路徑,並將自定義標記添加到所需頁面的底部。自定義標籤的位置很重要;它應該儘可能接近請求處理結束時被調用,因爲它僅在調用之前知道花費的時間(以及加載的對象)。

package com.foo.web.interceptor; 

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.springframework.web.servlet.ModelAndView; 
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 

public class PageGenerationTimeInterceptor extends HandlerInterceptorAdapter { 

    public static final String PAGE_START_TIME = "page_start_time"; 
    public static final String PAGE_GENERATION_TIME = "page_generation_time"; 

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
      Object handler) throws Exception { 
     request.setAttribute(PAGE_START_TIME, new Long(System.currentTimeMillis())); 
     return true; 
    } 

    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
      Object handler, ModelAndView modelAndView) throws Exception { 
     Long startTime = (Long) request.getAttribute(PAGE_START_TIME); 
     if (startTime != null) { 
      request.setAttribute(PAGE_GENERATION_TIME, new Long(System.currentTimeMillis() - startTime.longValue())); 
     } 
    } 
} 

的自定義標籤查找請求屬性,並利用它們來計算處理時間,觀看時間,總時間。它還可以查詢當前的Hibernate會話中的一級緩存統計信息,這可以揭示處理程序和視圖加載了多少對象。如果您不需要休眠信息,則可以刪除大的if塊。

package com.foo.web.taglib; 

import java.io.IOException; 
import java.util.HashMap; 
import java.util.Map; 
import java.util.SortedSet; 
import java.util.TreeSet; 

import javax.servlet.ServletContext; 
import javax.servlet.jsp.JspException; 
import javax.servlet.jsp.JspWriter; 
import javax.servlet.jsp.tagext.Tag; 
import javax.servlet.jsp.tagext.TryCatchFinally; 

import org.apache.log4j.LogManager; 
import org.apache.log4j.Logger; 
import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.engine.CollectionKey; 
import org.hibernate.engine.EntityKey; 
import org.hibernate.stat.SessionStatistics; 
import org.springframework.beans.factory.BeanFactoryUtils; 
import org.springframework.context.ApplicationContext; 
import org.springframework.web.bind.ServletRequestUtils; 
import org.springframework.web.context.support.WebApplicationContextUtils; 
import org.springframework.web.servlet.tags.RequestContextAwareTag; 

import com.foo.web.interceptor.PageGenerationTimeInterceptor; 

public class PageInfoTag extends RequestContextAwareTag implements TryCatchFinally { 
    private static final long serialVersionUID = -8448960221093136401L; 
    private static final Logger LOGGER = LogManager.getLogger(PageInfoTag.class); 
    public static final String SESSION_STATS_PARAM_NAME = "PageInfoTag.SessionStats"; 

    @Override 
    public int doStartTagInternal() throws JspException { 
     try { 
      JspWriter out = pageContext.getOut(); 
      Long startTime = (Long)pageContext.getRequest().getAttribute(PageGenerationTimeInterceptor.PAGE_START_TIME); 
      Long handlerTime = (Long)pageContext.getRequest().getAttribute(PageGenerationTimeInterceptor.PAGE_GENERATION_TIME); 
      if (startTime != null && handlerTime != null) { 
       long responseTime = System.currentTimeMillis() - startTime.longValue(); 
       long viewTime = responseTime - handlerTime; 
       out.append(String.format("<!-- total: %dms, handler: %dms, view: %dms -->", responseTime, handlerTime, viewTime)); 
      } 
      if (ServletRequestUtils.getBooleanParameter(pageContext.getRequest(), SESSION_STATS_PARAM_NAME, false)) { 
       //write another long HTML comment with information about contents of Hibernate first-level cache 
       ServletContext servletContext = pageContext.getServletContext(); 
       ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext); 
       String[] beans = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, 
         SessionFactory.class, false, false); 

       if (beans.length > 0) { 
        SessionFactory sessionFactory = (SessionFactory) context.getBean(beans[0]); 
        Session session = sessionFactory.getCurrentSession(); 
        SessionStatistics stats = session.getStatistics(); 
        Map<String, NamedCount> entityHistogram = new HashMap<String, NamedCount>(); 
        out.append("\n<!-- session statistics:\n"); 
        out.append("\tObject keys (").append(String.valueOf(stats.getEntityCount())).append("):\n"); 
        for (Object obj: stats.getEntityKeys()) { 
         EntityKey key = (EntityKey)obj; 
         out.append("\t\t").append(key.getEntityName()).append("#").append(key.getIdentifier().toString()).append("\n"); 
         increment(entityHistogram, key.getEntityName()); 
        } 
        out.append("\tObject key histogram:\n"); 
        SortedSet<NamedCount> orderedEntityHistogram = new TreeSet<NamedCount>(entityHistogram.values()); 
        for (NamedCount entry: orderedEntityHistogram) { 
         out.append("\t\t").append(entry.name).append(": ").append(String.valueOf(entry.count)).append("\n"); 
        } 
        Map<String, NamedCount> collectionHistogram = new HashMap<String, NamedCount>(); 
        out.append("\tCollection keys (").append(String.valueOf(stats.getCollectionCount())).append("):\n"); 
        for (Object obj: stats.getCollectionKeys()) { 
         CollectionKey key = (CollectionKey)obj; 
         out.append("\t\t").append(key.getRole()).append("#").append(key.getKey().toString()).append("\n"); 
         increment(collectionHistogram, key.getRole()); 
        } 
        out.append("\tCollection key histogram:\n"); 
        SortedSet<NamedCount> orderedCollectionHistogram = new TreeSet<NamedCount>(collectionHistogram.values()); 
        for (NamedCount entry: orderedCollectionHistogram) { 
         out.append("\t\t").append(entry.name).append(": ").append(String.valueOf(entry.count)).append("\n"); 
        } 
        out.append("-->"); 
       } 
      } 
     } catch (IOException e) { 
      LOGGER.error("Unable to write page info tag"); 
      throw new RuntimeException(e); 
     } 
     return Tag.EVAL_BODY_INCLUDE; 
    } 

    protected void increment(Map<String, NamedCount> histogram, String key) { 
     NamedCount count = histogram.get(key); 
     if (count == null) { 
      count = new NamedCount(key); 
      histogram.put(key, count); 
     } 
     count.count++; 
    } 

    class NamedCount implements Comparable<NamedCount> { 
     public String name; 
     public int count; 

     public NamedCount(String name) { 
      this.name = name; 
      count = 0; 
     } 

     @Override 
     public int compareTo(NamedCount other) { 
      //descending count, ascending name 
      int compared = other.count - this.count; 
      if (compared == 0) { 
       compared = this.name.compareTo(other.name); 
      } 
      return compared; 
     } 
    } 
} 
相關問題