不知道我的解決方案是否會幫助你,但這是我做的,因爲我需要類似的東西。
首先,我們需要記錄兩件事情,實例化時間和初始化時間。首先我使用%d {mm:ss,SSS}%m%n作爲模式(僅限時間和消息)爲包「org.springframework.beans.factory」啓用日誌記錄。 Spring會記錄如下消息:創建bean實例...並完成創建bean實例...對於第二件事情,我按照this answer中的建議創建了LoggerBeanPostProcessor。代碼是:
public class LoggerBeanPostProcessor implements BeanPostProcessor, Ordered {
protected Log logger = LogFactory.getLog("org.springframework.beans.factory.LoggerBeanPostProcessor");
private Map<String, Long> start;
private Map<String, Long> end;
public LoggerBeanPostProcessor() {
start = new HashMap<>();
end = new HashMap<>();
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
start.put(beanName, System.currentTimeMillis());
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
end.put(beanName, System.currentTimeMillis());
logger.debug("Init time for " + beanName + ": " + initializationTime(beanName));
return bean;
}
@Override
public int getOrder() {
return Integer.MAX_VALUE;
}
// this method returns initialization time of the bean.
public long initializationTime(String beanName) {
return end.get(beanName) - start.get(beanName);
}
}
我在log4j配置中使用文件appender。然後我寫了一個簡單的代碼來分析這些信息,並得到每個事物milisecond,總結他們:
public static void main(String[] argumentos) throws Exception{
File file = new File("C:\\app\\daily.log");
List<String> lines = FileUtils.readLines(file);
Map<String,Long> start = new HashMap();
Map<String,Long> end = new HashMap();
Map<String,Long> init = new HashMap();
List<String> beans = new ArrayList();
int max = 0;
for(String line : lines) {
String time = StringUtils.substring(line, 0, 9);
String msg = StringUtils.substring(line, 10);
if(msg.startsWith("Creating instance")) {
int fi = StringUtils.indexOf(msg, '\'') + 1;
int li = StringUtils.lastIndexOf(msg, '\'');
String bean = StringUtils.substring(msg, fi, li);
if(start.containsKey(bean)) {
continue;
}
start.put(bean, parseTime(time));
beans.add(bean);
max = Math.max(max, bean.length());
} else if(msg.startsWith("Finished creating")) {
int fi = StringUtils.indexOf(msg, '\'') + 1;
int li = StringUtils.lastIndexOf(msg, '\'');
String bean = StringUtils.substring(msg, fi, li);
if(end.containsKey(bean)) {
continue;
}
end.put(bean, parseTime(time));
} else if(msg.startsWith("Init time for")) {
int li = StringUtils.lastIndexOf(msg, ':');
String bean = StringUtils.substring(msg, 14, li);
if(init.containsKey(bean)) {
continue;
}
init.put(bean, Long.parseLong(StringUtils.substring(msg, li+2)));
}
}
for(String bean : beans) {
long s = start.get(bean);
long e = end.get(bean);
long i = init.containsKey(bean) ? init.get(bean) : -1;
System.out.println(StringUtils.leftPad(bean, max) + ": " + StringUtils.leftPad(Long.toString((e-s)+i), 6, ' '));
}
}
在由此產生:
splashScreen: 172
org.springframework.aop.config.internalAutoProxyCreator: 31
loggerBeanPostProcessor: 1137
appContext: 1122
希望這有助於你儘可能多地幫助了我。
感謝您的回答,但分析並不能解決我的問題(請參閱更新後的問題) –
因此,您說您沒有可配置的QA環境?由於您正在討論初始化時間,因此您不需要實際的應用程序負載,因此QA環境中的值與實際生產環境類似,但當然CPU性能除外,但相對您可以識別有問題的豆子。 – Andreas
由於bean執行的初始化設置特定,它們的性能可能會根據不同的設置而改變。當然,我們正在使用分析來識別許多問題,但我正在尋找額外的工具來識別問題。 –