package com.anjlab.ping.pages;
import static com.anjlab.ping.services.profiler.ProfilingAdvice.dumpCallStack;
import static com.anjlab.ping.services.profiler.ProfilingAdvice.dumpPlainMetrics;
import static com.anjlab.ping.services.profiler.ProfilingAdvice.getLeaf;
import static java.lang.Integer.toHexString;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.beaneditor.BeanModel;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.BeanModelSource;
import com.anjlab.ping.services.profiler.Leaf;
import com.anjlab.ping.services.profiler.ProfilerMetric;
import com.anjlab.ping.services.profiler.ProfilingAdvice;
import com.anjlab.tapestry5.AbstractReadonlyPropertyConduit;
public class Profiler {
@Property private String signature;
@Property private Map<String, Leaf> metrics;
private List<String> context;
public void onActivate(String context) {
this.items.clear();
this.context = new ArrayList<String>();
if (context != null) {
if (!context.contains("-")) {
this.context.add(context);
} else {
for (String string : context.split("\\-")) {
this.context.add(string);
}
}
}
}
public String onPassivate() {
return listToWebString(context);
}
private String listToWebString(List<String> list) {
return list == null ? "" : list.toString().replaceAll("\\[|\\]", "").replaceAll(", ", "-");
}
public Set<String> getMethods() {
if ("callstack".equals(getView())) {
metrics = dumpCallStack(getTracePath());
} else {
metrics = dumpPlainMetrics();
}
return metrics.keySet();
}
public List<String> getTracePath() {
return context == null || context.size() <= 1
? Collections.<String>emptyList()
: context.subList(1, context.size());
}
private String getView() {
return context == null || context.size() == 0
? null
: context.get(0);
}
@Inject private BeanModelSource beanModelSource;
@Inject private Messages messages;
public BeanModel<?> getModel() {
BeanModel<?> beanModel = beanModelSource.createDisplayModel(String.class, messages);
beanModel.add("signature", new AbstractReadonlyPropertyConduit()
{
@Override
public Object get(Object instance) {
return instance;
}
});
beanModel.add("invocationCount", new AbstractReadonlyPropertyConduit()
{
@Override
public Object get(Object instance) {
return metrics.get(instance).getMetric().invocationCount;
}
});
beanModel.add("totalTimeMillis", new AbstractReadonlyPropertyConduit()
{
@Override
public Object get(Object instance) {
return metrics.get(instance).getMetric().totalTimeMillis;
}
});
beanModel.add("avgTimeMillis", new AbstractReadonlyPropertyConduit()
{
@Override
public Object get(Object instance) {
ProfilerMetric metric = metrics.get(instance).getMetric();
if (metric.totalTimeMillis == 0) {
return 0;
}
return (int) (metric.totalTimeMillis / metric.invocationCount);
}
});
if ("callstack".equals(getView())) {
beanModel.add("drilldown", null);
} else {
beanModel.add("traceInto", null);
}
beanModel.exclude("empty");
return beanModel;
}
@Property private String item;
/*
* Call stack path
*/
private List<String> items = new ArrayList<String>();
public Leaf getItemLeaf() {
if ("callstack".equals(item)) {
return new Leaf(item, null);
}
items.add(item);
Leaf leaf = getLeaf(items);
if (leaf == null) {
leaf = new Leaf(item, null);
}
return leaf;
}
public String getItemContext() {
List<String> tracePath = new ArrayList<String>();
tracePath.add("callstack");
tracePath.addAll(items);
return listToWebString(tracePath);
}
public int getItemPaddingLeft() {
return items.size() * 20;
}
/*
* End of call stack path
*/
public String getTraceIntoContext() {
Leaf leaf = metrics.get(signature);
List<String> tracePath = new ArrayList<String>();
tracePath.add(toHexString(leaf.getMethodName().hashCode()));
while ((leaf = leaf.getParent()) != null) {
tracePath.add(0, toHexString(leaf.getMethodName().hashCode()));
}
tracePath.add(0, "callstack");
return listToWebString(tracePath);
}
public String getDrilldownContext() {
List<String> context = new ArrayList<String>();
for (String string : this.context) {
context.add(string);
}
context.add(toHexString(signature.hashCode()));
return listToWebString(context);
}
public void onActionFromResetStatistics() {
ProfilingAdvice.clear();
}
}