提交 d883535b 编写于 作者: F Frankie Wu

implement 4 graphs in transaction page

上级 a4356bfd
package com.dianping.cat.consumer.transaction;
import com.dianping.cat.consumer.transaction.model.entity.Range;
import com.dianping.cat.consumer.transaction.model.entity.TransactionName;
import com.dianping.cat.consumer.transaction.model.entity.TransactionType;
import com.dianping.cat.consumer.transaction.model.transform.BaseVisitor;
......@@ -7,6 +8,8 @@ import com.dianping.cat.consumer.transaction.model.transform.BaseVisitor;
public class MeanSquareDeviationComputer extends BaseVisitor {
@Override
public void visitName(TransactionName name) {
super.visitName(name);
long count = name.getTotalCount();
if (count > 0) {
......@@ -21,6 +24,13 @@ public class MeanSquareDeviationComputer extends BaseVisitor {
}
}
@Override
public void visitRange(Range range) {
if (range.getCount() > 0) {
range.setAvg(range.getSum() / range.getCount());
}
}
@Override
public void visitType(TransactionType type) {
super.visitType(type);
......
......@@ -4,6 +4,7 @@ import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
......@@ -18,6 +19,8 @@ import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationExce
import com.dianping.cat.configuration.model.entity.Config;
import com.dianping.cat.configuration.model.entity.Property;
import com.dianping.cat.consumer.transaction.model.entity.Duration;
import com.dianping.cat.consumer.transaction.model.entity.Range;
import com.dianping.cat.consumer.transaction.model.entity.TransactionName;
import com.dianping.cat.consumer.transaction.model.entity.TransactionReport;
import com.dianping.cat.consumer.transaction.model.entity.TransactionType;
......@@ -219,6 +222,8 @@ public class TransactionAnalyzer extends AbstractMessageAnalyzer<TransactionRepo
type.setSum(type.getSum() + duration);
type.setSum2(type.getSum2() + duration * duration);
processTransactionGrpah(name, t);
List<Message> children = t.getChildren();
for (Message child : children) {
......@@ -230,6 +235,31 @@ public class TransactionAnalyzer extends AbstractMessageAnalyzer<TransactionRepo
return count;
}
void processTransactionGrpah(TransactionName name, Transaction t) {
long d = t.getDuration();
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(t.getTimestamp());
int min = cal.get(Calendar.MINUTE);
int dk = 1;
int tk = min - min % 5;
while (dk < d) {
dk <<= 1;
}
Duration duration = name.findOrCreateDuration(dk);
Range range = name.findOrCreateRange(tk);
duration.incCount();
range.incCount();
if (!t.isSuccess()) {
range.incFails();
}
range.setSum(range.getSum() + d);
}
public void setAnalyzerInfo(long startTime, long duration, String domain, long extraTime) {
m_extraTime = extraTime;
m_startTime = startTime;
......
......@@ -41,7 +41,7 @@
<entity name="range">
<attribute name="value" value-type="int" />
<attribute name="count" value-type="int" />
<attribute name="sum" value-type="int" />
<attribute name="sum" value-type="double" />
<attribute name="avg" value-type="double" />
<attribute name="fails" value-type="int" />
</entity>
......
......@@ -38,7 +38,7 @@
<entity name="range">
<attribute name="value" value-type="int" primitive="true" key="true" />
<attribute name="count" value-type="int" primitive="true" method-inc="true" />
<attribute name="sum" value-type="int" primitive="true" />
<attribute name="sum" value-type="double" primitive="true" />
<attribute name="avg" value-type="double" primitive="true" format="0.0" />
<attribute name="fails" value-type="int" primitive="true" method-inc="true" />
</entity>
......
......@@ -13,22 +13,36 @@ public abstract class AbstractGraphPayload implements GraphPayload {
m_title = title;
m_axisXLabel = axisXLabel;
m_axisYLabel = axisYLabel;
m_values = getValues();
}
public final double[] getValues() {
if (m_values == null) {
m_values = loadValues();
}
return m_values;
}
protected abstract double[] loadValues();
@Override
public String getAxisXLabel(int index) {
return String.valueOf(index);
}
@Override
public String getAxisXLabel() {
public String getAxisXTitle() {
return m_axisXLabel;
}
@Override
public String getAxisYLabel() {
public String getAxisYTitle() {
return m_axisYLabel;
}
@Override
public int getColumns() {
return m_values.length;
return getValues().length;
}
@Override
......@@ -48,12 +62,12 @@ public abstract class AbstractGraphPayload implements GraphPayload {
@Override
public int getHeight() {
return 280;
return 250;
}
@Override
public int getMarginBottom() {
return 50;
return 60;
}
@Override
......@@ -68,7 +82,7 @@ public abstract class AbstractGraphPayload implements GraphPayload {
@Override
public int getMarginTop() {
return 50;
return 40;
}
@Override
......@@ -85,4 +99,14 @@ public abstract class AbstractGraphPayload implements GraphPayload {
public int getWidth() {
return 580;
}
@Override
public boolean isAxisXLabelRotated() {
return false;
}
@Override
public boolean isAxisXLabelSkipped() {
return getValues().length >= 16;
}
}
......@@ -14,7 +14,11 @@ public class DefaultGraphBuilder implements GraphBuilder {
int maxValue = m_translater.getMaxValue(values);
XmlBuilder b = new XmlBuilder();
buildHeader(payload, b);
if (maxValue < payload.getRows()) {
maxValue = payload.getRows();
}
buildHeader(payload, b, maxValue);
buildCoordinate(payload, b);
buildYLabels(payload, b, maxValue);
buildXLabels(payload, b);
......@@ -109,7 +113,7 @@ public class DefaultGraphBuilder implements GraphBuilder {
b.tag("path", "id", "ys", "d", p.build());
}
if (cols >= 16) {
if (payload.isAxisXLabelSkipped()) {
p.moveTo(left, top + h).mark().v(9).m(xstep, -9).v(5).m(xstep, -5).repeat(cols / 2);
if (cols % 2 == 0) {
......@@ -129,7 +133,7 @@ public class DefaultGraphBuilder implements GraphBuilder {
b.tag2("svg");
}
protected void buildHeader(GraphPayload payload, XmlBuilder b) {
protected void buildHeader(GraphPayload payload, XmlBuilder b, int maxValue) {
int height = payload.getHeight();
int width = payload.getWidth();
int top = payload.getMarginTop();
......@@ -153,22 +157,23 @@ public class DefaultGraphBuilder implements GraphBuilder {
b.tag1("g");
String axisXLabel = payload.getAxisXLabel();
String axisXTitle = payload.getAxisXTitle();
if (axisXLabel != null) {
int x = (width - left - right - axisXLabel.length() * 9) / 2 + left;
if (axisXTitle != null) {
int x = (width - left - right - axisXTitle.length() * 9) / 2 + left;
int y = height - 4;
b.tagWithText("text", axisXLabel, "x", x, "y", y, "font-size", "18");
b.tagWithText("text", axisXTitle, "x", x, "y", y, "font-size", "18");
}
String axisYLabel = payload.getAxisYLabel();
String axisYTitle = payload.getAxisYTitle();
if (axisYLabel != null) {
int x = 16;
int y = (height - top - bottom + axisYLabel.length() * 9) / 2 + top;
if (axisYTitle != null) {
int x = left - 20 - String.valueOf(maxValue).length() * 9;
int y = (height - top - bottom + axisYTitle.length() * 9) / 2 + top;
String transform = "rotate(-90," + x + "," + y + ")";
b.tagWithText("text", axisYLabel, "x", x, "y", y, "font-size", "18", "transform", transform);
b.tagWithText("text", axisYTitle, "x", x, "y", y, "font-size", "18", "transform", transform);
}
if (title != null) {
......@@ -192,27 +197,34 @@ public class DefaultGraphBuilder implements GraphBuilder {
b.tag1("g", "id", "xt");
if (cols >= 16) {
for (int i = 0; i <= cols; i += 2) {
int x = left + xstep * i - 4;
int y = height - bottom + 22;
boolean rotated = payload.isAxisXLabelRotated();
boolean skipped = payload.isAxisXLabelSkipped();
if (i >= 10) {
x -= 4;
}
for (int i = 0; i <= cols;) {
int x = left + xstep * i - 4;
int y = height - bottom + 20 + (skipped ? 2 : 0);
String label = payload.getAxisXLabel(i);
b.tagWithText("text", i, "x", x, "y", y);
if (!rotated) {
if (label.length() > 1) {
x -= 4 * (label.length() - 1);
}
} else {
y -= 10;
}
} else {
for (int i = 0; i <= cols; i++) {
int x = left + xstep * i - 4;
int y = height - bottom + 20;
if (i >= 10) {
x -= 4;
}
if (rotated) {
String transform = "rotate(90," + x + "," + y + ")";
b.tagWithText("text", label, "x", x, "y", y, "transform", transform);
} else {
b.tagWithText("text", label, "x", x, "y", y);
}
b.tagWithText("text", i, "x", x, "y", y);
if (skipped) {
i += 2;
} else {
i++;
}
}
......
......@@ -25,7 +25,7 @@ public class DefaultValueTranslater implements ValueTranslater {
while (maxValue > max * 2) {
maxValue = maxValue / 2;
}
return maxValue;
}
......
package com.dianping.cat.report.graph;
public interface GraphPayload {
public String getAxisXLabel();
public String getAxisXTitle();
public String getAxisYLabel();
public String getAxisYTitle();
public String getAxisXLabel(int index);
public int getColumns();
......@@ -30,4 +32,8 @@ public interface GraphPayload {
public int getDisplayHeight();
public int getDisplayWidth();
public boolean isAxisXLabelRotated();
public boolean isAxisXLabelSkipped();
}
......@@ -4,25 +4,24 @@ import java.util.ArrayList;
import java.util.List;
import com.dianping.cat.consumer.ip.model.entity.IpReport;
import com.dianping.cat.report.ReportPage;
import com.dianping.cat.report.page.AbstractReportModel;
import com.dianping.cat.report.view.UrlNav;
import com.site.web.mvc.ViewModel;
public class Model extends ViewModel<ReportPage, Action, Context> {
public class Model extends AbstractReportModel<Action, Context> {
private IpReport m_report;
private List<DisplayModel> m_displayModels;
private List<String> m_domains;
private String m_currentDomain;
private String m_current;
private String m_reportTitle;
private String m_generateTime;
private String m_urlPrefix;
private List<UrlNav> m_urlNavs;
......@@ -44,30 +43,30 @@ public class Model extends ViewModel<ReportPage, Action, Context> {
public List<String> getDomains() {
return m_domains;
}
public String getUrlPrefix() {
return m_urlPrefix;
}
return m_urlPrefix;
}
public void setUrlPrefix(String urlPrefix) {
m_urlPrefix = urlPrefix;
}
m_urlPrefix = urlPrefix;
}
public List<UrlNav> getUrlNavs() {
return m_urlNavs;
}
return m_urlNavs;
}
public void setUrlNavs(List<UrlNav> urlNavs) {
m_urlNavs = urlNavs;
}
m_urlNavs = urlNavs;
}
public String getCurrentDomain() {
return m_currentDomain;
}
return m_currentDomain;
}
public void setCurrentDomain(String currentDomain) {
m_currentDomain = currentDomain;
}
m_currentDomain = currentDomain;
}
public IpReport getReport() {
return m_report;
......@@ -106,11 +105,11 @@ public class Model extends ViewModel<ReportPage, Action, Context> {
}
public String getGenerateTime() {
return m_generateTime;
}
return m_generateTime;
}
public void setGenerateTime(String generateTime) {
m_generateTime = generateTime;
}
m_generateTime = generateTime;
}
}
......@@ -40,12 +40,13 @@ public class ModelRequest {
}
}
public void setProperty(String name, String value) {
public ModelRequest setProperty(String name, String value) {
if (m_properties == null) {
m_properties = new HashMap<String, String>();
}
m_properties.put(name, value);
return this;
}
public static ModelRequest from(String domain, String period) {
......
package com.dianping.cat.report.page.transaction;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import com.dianping.cat.consumer.transaction.MeanSquareDeviationComputer;
import com.dianping.cat.consumer.transaction.model.entity.Duration;
import com.dianping.cat.consumer.transaction.model.entity.Range;
import com.dianping.cat.consumer.transaction.model.entity.TransactionName;
import com.dianping.cat.consumer.transaction.model.entity.TransactionReport;
import com.dianping.cat.consumer.transaction.model.entity.TransactionType;
import com.dianping.cat.report.ReportPage;
import com.dianping.cat.report.graph.AbstractGraphPayload;
import com.dianping.cat.report.graph.GraphBuilder;
......@@ -21,7 +31,7 @@ import com.site.web.mvc.annotation.PayloadMeta;
* @author sean.wang
* @since Feb 6, 2012
*/
public class Handler implements PageHandler<Context> {
public class Handler implements PageHandler<Context>, Initializable {
@Inject
private JspViewer m_jspViewer;
......@@ -31,6 +41,42 @@ public class Handler implements PageHandler<Context> {
@Inject
private GraphBuilder m_builder;
private Map<Integer, Integer> m_map = new HashMap<Integer, Integer>();
private MeanSquareDeviationComputer m_computer = new MeanSquareDeviationComputer();
private TransactionName getName(Payload payload) {
String domain = payload.getDomain();
String type = payload.getType();
String name = payload.getName();
ModelRequest request = new ModelRequest(domain, payload.getPeriod()) //
.setProperty("type", type).setProperty("name", name);
ModelResponse<TransactionReport> response = m_service.invoke(request);
TransactionReport report = response.getModel();
TransactionType t = report.findType(type);
if (t != null) {
TransactionName n = t.findName(name);
if (n != null) {
n.accept(m_computer);
}
return n;
}
return null;
}
private TransactionReport getReport(Payload payload) {
String domain = payload.getDomain();
ModelRequest request = new ModelRequest(domain, payload.getPeriod());
ModelResponse<TransactionReport> response = m_service.invoke(request);
TransactionReport report = response.getModel();
return report;
}
@Override
@PayloadMeta(Payload.class)
@InboundActionMeta(name = "t")
......@@ -52,36 +98,201 @@ public class Handler implements PageHandler<Context> {
showReport(model, payload);
break;
case GRAPHS:
String graph = m_builder.build(new AbstractGraphPayload("Duration Chart", "Hour of day", "Average time(ms)") {
@Override
public double[] getValues() {
double[] values = new double[12];
showGraphs(model, payload);
break;
}
for (int i = 0; i < values.length; i++) {
values[i] = Math.random() * (i + 1) * 110;
}
m_jspViewer.view(ctx, model);
}
return values;
}
});
@Override
public void initialize() throws InitializationException {
int k = 1;
model.setGraph(graph);
break;
m_map.put(0, 0);
for (int i = 0; i < 17; i++) {
m_map.put(k, i);
k <<= 1;
}
}
private void showGraphs(Model model, Payload payload) {
final TransactionName name = getName(payload);
if (name == null) {
return;
}
m_jspViewer.view(ctx, model);
String graph1 = m_builder.build(new DurationPayload("Transaction Duration", "Duration (ms)", "Count", name));
String graph2 = m_builder.build(new HitPayload("Hits Over Time", "Time (min)", "Count", name));
String graph3 = m_builder.build(new AverageTimePayload("Average Duration Over Time", "Time (min)",
"Average Duration (ms)", name));
String graph4 = m_builder.build(new FailurePayload("Failures Over Time", "Time (min)", "Count", name));
model.setGraph1(graph1);
model.setGraph2(graph2);
model.setGraph3(graph3);
model.setGraph4(graph4);
}
private void showReport(Model model, Payload payload) {
try {
String domain = payload.getDomain();
ModelRequest request = new ModelRequest(domain, payload.getPeriod());
ModelResponse<TransactionReport> response = m_service.invoke(request);
TransactionReport report = response.getModel();
TransactionReport report = getReport(payload);
report.accept(m_computer);
model.setReport(report);
} catch (Throwable e) {
model.setException(e);
}
}
abstract class AbstractPayload extends AbstractGraphPayload {
public AbstractPayload(String title, String axisXLabel, String axisYLabel) {
super(title, axisXLabel, axisYLabel);
}
@Override
public int getWidth() {
return super.getWidth() + 120;
}
@Override
public int getDisplayHeight() {
return (int) (super.getDisplayHeight() * 0.7);
}
@Override
public int getDisplayWidth() {
return (int) (super.getDisplayWidth() * 0.7);
}
@Override
public String getAxisXLabel(int index) {
return String.valueOf(index * 5);
}
}
final class AverageTimePayload extends AbstractPayload {
private final TransactionName m_name;
public AverageTimePayload(String title, String axisXLabel, String axisYLabel, TransactionName name) {
super(title, axisXLabel, axisYLabel);
m_name = name;
}
@Override
protected double[] loadValues() {
double[] values = new double[12];
for (Range range : m_name.getRanges()) {
int value = range.getValue();
int k = value / 5;
values[k] += range.getAvg();
}
return values;
}
}
final class DurationPayload extends AbstractPayload {
private final TransactionName m_name;
public DurationPayload(String title, String axisXLabel, String axisYLabel, TransactionName name) {
super(title, axisXLabel, axisYLabel);
m_name = name;
}
@Override
public String getAxisXLabel(int index) {
if (index == 0) {
return "0";
}
int k = 1;
for (int i = 1; i < index; i++) {
k <<= 1;
}
return String.valueOf(k);
}
@Override
public boolean isAxisXLabelRotated() {
return true;
}
@Override
public boolean isAxisXLabelSkipped() {
return false;
}
@Override
protected double[] loadValues() {
double[] values = new double[17];
for (Duration duration : m_name.getDurations()) {
int d = duration.getValue();
Integer k = m_map.get(d);
if (k != null) {
values[k] += duration.getCount();
}
}
return values;
}
}
final class FailurePayload extends AbstractPayload {
private final TransactionName m_name;
public FailurePayload(String title, String axisXLabel, String axisYLabel, TransactionName name) {
super(title, axisXLabel, axisYLabel);
m_name = name;
}
@Override
protected double[] loadValues() {
double[] values = new double[12];
for (Range range : m_name.getRanges()) {
int value = range.getValue();
int k = value / 5;
values[k] += range.getFails();
}
return values;
}
}
final class HitPayload extends AbstractPayload {
private final TransactionName m_name;
public HitPayload(String title, String axisXLabel, String axisYLabel, TransactionName name) {
super(title, axisXLabel, axisYLabel);
m_name = name;
}
@Override
protected double[] loadValues() {
double[] values = new double[12];
for (Range range : m_name.getRanges()) {
int value = range.getValue();
int k = value / 5;
values[k] += range.getCount();
}
return values;
}
}
}
......@@ -16,7 +16,13 @@ public class Model extends ViewModel<ReportPage, Action, Context> {
private Throwable m_exception;
private String m_graph;
private String m_graph1;
private String m_graph2;
private String m_graph3;
private String m_graph4;
public Model(Context ctx) {
super(ctx);
......@@ -49,10 +55,22 @@ public class Model extends ViewModel<ReportPage, Action, Context> {
return m_exception;
}
public String getGraph() {
return m_graph;
public String getGraph1() {
return m_graph1;
}
public String getGraph2() {
return m_graph2;
}
public String getGraph3() {
return m_graph3;
}
public String getGraph4() {
return m_graph4;
}
public String getLogViewBaseUri() {
return buildPageUri(ReportPage.LOGVIEW.getPath(), null);
}
......@@ -74,10 +92,22 @@ public class Model extends ViewModel<ReportPage, Action, Context> {
m_exception = exception;
}
public void setGraph(String graph) {
m_graph = graph;
public void setGraph1(String graph1) {
m_graph1 = graph1;
}
public void setGraph2(String graph2) {
m_graph2 = graph2;
}
public void setGraph3(String graph3) {
m_graph3 = graph3;
}
public void setGraph4(String graph4) {
m_graph4 = graph4;
}
public void setReport(TransactionReport report) {
m_report = report;
}
......
......@@ -11,11 +11,6 @@
font-size: small;
}
.graph {
width: 400px;
height: 100px;
}
tr.odd td {
background-color: #eee;
font-size: small;
......@@ -47,4 +42,8 @@ tr.link td {
.error {
color: red;
}
.graphs {
height: 1px;
}
\ No newline at end of file
......@@ -45,7 +45,7 @@
<td><a href="${model.logViewBaseUri}/${empty e.failMessageUrl ? e.successMessageUrl : e.failMessageUrl}">Log View</a></td>
<td>${w:format(e.min,'0')}/${w:format(e.max,'0')}/${w:format(e.avg,'0.0')}/${w:format(e.std,'0.0')}</td>
</tr>
<tr class="graphs"><td>&nbsp;</td><td colspan="5"><div id="${status.index}"></div></td></tr>
<tr class="graphs"><td colspan="6"><div id="${status.index}"></div></td></tr>
</c:forEach>
</c:otherwise>
</c:choose>
......
<%@ page contentType="image/html; charset=utf-8" %>
<%@ page contentType="text/html; charset=utf-8"%>
<jsp:useBean id="ctx" type="com.dianping.cat.report.page.transaction.Context" scope="request" />
<jsp:useBean id="payload" type="com.dianping.cat.report.page.transaction.Payload" scope="request" />
<jsp:useBean id="model" type="com.dianping.cat.report.page.transaction.Model" scope="request" />
${model.graph}
\ No newline at end of file
<table>
<tr>
<td>${model.graph1}</td>
<td>${model.graph2}</td>
</tr>
<tr>
<td>${model.graph3}</td>
<td>${model.graph4}</td>
</tr>
</table>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册