提交 32ac725c 编写于 作者: Y yong.you

增加产品线监控图

上级 c6b8d771
......@@ -23,8 +23,10 @@ import com.dianping.cat.consumer.core.dal.TaskDao;
import com.dianping.cat.consumer.core.problem.ProblemHandler;
import com.dianping.cat.consumer.problem.model.entity.Duration;
import com.dianping.cat.consumer.problem.model.entity.Entry;
import com.dianping.cat.consumer.problem.model.entity.JavaThread;
import com.dianping.cat.consumer.problem.model.entity.Machine;
import com.dianping.cat.consumer.problem.model.entity.ProblemReport;
import com.dianping.cat.consumer.problem.model.entity.Segment;
import com.dianping.cat.consumer.problem.model.transform.BaseVisitor;
import com.dianping.cat.consumer.problem.model.transform.DefaultSaxParser;
import com.dianping.cat.consumer.problem.model.transform.DefaultXmlBuilder;
......@@ -84,17 +86,20 @@ public class ProblemAnalyzer extends AbstractMessageAnalyzer<ProblemReport> impl
@Override
public ProblemReport getReport(String domain) {
ProblemReport report = m_reports.get(domain);
if (!ALL.equals(domain)) {
ProblemReport report = m_reports.get(domain);
if (report == null) {
report = new ProblemReport(domain);
if (report == null) {
report = new ProblemReport(domain);
report.setStartTime(new Date(m_startTime));
report.setEndTime(new Date(m_startTime + MINUTE * 60 - 1));
report.setStartTime(new Date(m_startTime));
report.setEndTime(new Date(m_startTime + MINUTE * 60 - 1));
}
report.getDomainNames().addAll(m_reports.keySet());
return report;
} else {
return buildTotalProblemReport();
}
report.getDomainNames().addAll(m_reports.keySet());
return report;
}
@Override
......@@ -229,6 +234,8 @@ public class ProblemAnalyzer extends AbstractMessageAnalyzer<ProblemReport> impl
private String m_currentState;
private String m_currentThread;
public ProblemReportVisitor(ProblemReport report) {
m_report = report;
}
......@@ -272,5 +279,28 @@ public class ProblemAnalyzer extends AbstractMessageAnalyzer<ProblemReport> impl
super.visitProblemReport(problemReport);
}
@Override
public void visitMachine(Machine machine) {
super.visitMachine(machine);
}
@Override
public void visitSegment(Segment segment) {
int minute = segment.getId();
int count = segment.getCount();
Machine machine = m_report.findOrCreateMachine(m_currentDomain);
Entry entry = findOrCreatEntry(machine, m_currentType, m_currentState);
JavaThread thread = entry.findOrCreateThread(m_currentThread);
Segment temp = thread.findOrCreateSegment(minute);
temp.setCount(temp.getCount() + count);
}
@Override
public void visitThread(JavaThread thread) {
m_currentThread = thread.getId();
super.visitThread(thread);
}
}
}
......@@ -245,8 +245,13 @@ public class DefaultMessageManager extends ContainerHolder implements MessageMan
manager.flush(tree);
} else {
Transaction entry = m_stack.peek();
entry.addChild(message);
List<Message> childrens = entry.getChildren();
if (childrens != null && childrens.size() < 1000) {
entry.addChild(message);
}else{
System.out.println("Child is to many");
}
// entry.addChild(message);
}
}
......
......@@ -32,6 +32,7 @@ import com.dianping.cat.report.graph.DefaultValueTranslater;
import com.dianping.cat.report.graph.GraphBuilder;
import com.dianping.cat.report.graph.ValueTranslater;
import com.dianping.cat.report.page.PayloadNormalizer;
import com.dianping.cat.report.page.dependency.dashboard.DashboardConfig;
import com.dianping.cat.report.page.dependency.graph.TopologyGraphBuilder;
import com.dianping.cat.report.page.dependency.graph.TopologyGraphConfigManger;
import com.dianping.cat.report.page.dependency.graph.TopologyGraphItemBuilder;
......@@ -206,17 +207,20 @@ public class ComponentsConfigurator extends AbstractResourceConfigurator {
.req(WeeklyReportCache.class, MonthReportCache.class));
all.add(C(EventCollectManager.class).req(EventDao.class, ServerConfigManager.class));
all.add(C(TopologyGraphConfigManger.class));
all.add(C(TopologyGraphItemBuilder.class).req(TopologyGraphConfigManger.class));
all.add(C(TopologyGraphBuilder.class).req(TopologyGraphItemBuilder.class));
// model service
all.addAll(new ServiceComponentConfigurator().defineComponents());
all.add(C(TopologyGraphManager.class).req(TopologyGraphBuilder.class).req(ModelService.class, "dependency"));
all.add(C(DashboardConfig.class));
all.add(C(TopologyGraphManager.class).req(TopologyGraphBuilder.class, ServerConfigManager.class)//
.req(DashboardConfig.class).req(ModelService.class, "dependency"));
// database
all.add(C(JdbcDataSourceConfigurationManager.class) //
......
......@@ -23,6 +23,8 @@ public class CatString {
public static final String EXCEPTION_COUNT = "错误数";
public static final String EXCEPTION_INFO = "异常信息";
public static final String ZABBIX_ERROR = "Zabbix告警";
public static final String SUCCESS = "Success";
......
......@@ -3,7 +3,9 @@ package com.dianping.cat.report.page.dependency;
public enum Action implements org.unidal.web.mvc.Action {
VIEW("view"),
GRAPH("dependencyGraph");
GRAPH("dependencyGraph"),
DASHBOARD("dashboard"),;
private String m_name;
......
package com.dianping.cat.report.page.dependency;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import com.dianping.cat.consumer.problem.model.entity.Duration;
import com.dianping.cat.consumer.problem.model.entity.Entry;
import com.dianping.cat.consumer.problem.model.entity.ProblemReport;
import com.dianping.cat.consumer.problem.model.entity.Segment;
import com.dianping.cat.consumer.problem.model.transform.BaseVisitor;
import com.dianping.cat.helper.CatString;
import com.dianping.cat.helper.MapUtils;
import com.dianping.cat.helper.TimeUtil;
import com.dianping.cat.report.page.dependency.graph.GraphConstrant;
public class ExceptionInfoBuilder extends BaseVisitor {
private Map<String, Integer> m_errors = new LinkedHashMap<String, Integer>();
private Date m_start;
@Override
public void visitEntry(Entry entry) {
String type = entry.getType();
......@@ -36,6 +42,12 @@ public class ExceptionInfoBuilder extends BaseVisitor {
}
}
@Override
public void visitProblemReport(ProblemReport problemReport) {
m_start = problemReport.getStartTime();
super.visitProblemReport(problemReport);
}
@Override
public void visitSegment(Segment segment) {
super.visitSegment(segment);
......@@ -49,10 +61,13 @@ public class ExceptionInfoBuilder extends BaseVisitor {
return arg1.getValue() - arg0.getValue();
}
};
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
if (m_errors.size() > 0) {
sb.append("<span style='color:red'>").append("------").append(CatString.EXCEPTION_INFO).append("------")
.append("</span>").append(GraphConstrant.ENTER);
sb.append(GraphConstrant.LINE).append(GraphConstrant.ENTER);
sb.append("<span style='color:red'>").append(CatString.EXCEPTION_INFO).append("(");
sb.append(sdf.format(m_start)).append("-")
.append(sdf.format(new Date(m_start.getTime() + TimeUtil.ONE_HOUR - 1))).append(")");
sb.append("</span>").append(GraphConstrant.ENTER);
}
m_errors = MapUtils.sortMap(m_errors, compator);
for (java.util.Map.Entry<String, Integer> error : m_errors.entrySet()) {
......
......@@ -5,10 +5,12 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import javax.servlet.ServletException;
......@@ -25,14 +27,17 @@ import com.dianping.cat.consumer.dependency.model.entity.DependencyReport;
import com.dianping.cat.consumer.dependency.model.entity.Index;
import com.dianping.cat.consumer.dependency.model.entity.Segment;
import com.dianping.cat.consumer.problem.model.entity.ProblemReport;
import com.dianping.cat.helper.CatString;
import com.dianping.cat.helper.TimeUtil;
import com.dianping.cat.home.dal.report.Event;
import com.dianping.cat.home.dependency.graph.entity.Edge;
import com.dianping.cat.home.dependency.graph.entity.Node;
import com.dianping.cat.home.dependency.graph.entity.TopologyGraph;
import com.dianping.cat.home.dependency.graph.transform.DefaultJsonBuilder;
import com.dianping.cat.report.ReportPage;
import com.dianping.cat.report.page.LineChart;
import com.dianping.cat.report.page.PayloadNormalizer;
import com.dianping.cat.report.page.dependency.dashboard.DashboardGraph;
import com.dianping.cat.report.page.dependency.graph.GraphConstrant;
import com.dianping.cat.report.page.dependency.graph.LineGraphBuilder;
import com.dianping.cat.report.page.dependency.graph.TopologyGraphManager;
......@@ -43,29 +48,31 @@ import com.dianping.cat.report.page.model.spi.ModelResponse;
import com.dianping.cat.report.page.model.spi.ModelService;
public class Handler implements PageHandler<Context> {
@Inject
private JspViewer m_jspViewer;
@Inject
private EventCollectManager m_manager;
@Inject(type = ModelService.class, value = "dependency")
private ModelService<DependencyReport> m_dependencyService;
@Inject
private PayloadNormalizer m_normalizePayload;
private EventCollectManager m_eventManager;
@Inject
private TopologyGraphManager m_graphManager;
@Inject
private JspViewer m_jspViewer;
@Inject
private PayloadNormalizer m_normalizePayload;
@Inject(type = ModelService.class, value = "problem")
private ModelService<ProblemReport> m_problemservice;
private SimpleDateFormat m_sdf = new SimpleDateFormat("HH:mm");
private Set<String> m_nodes;
private SimpleDateFormat m_dateFormat = new SimpleDateFormat("yyyyMMddHH");
private Segment buildAllSegment(DependencyReport report) {
private SimpleDateFormat m_sdf = new SimpleDateFormat("HH:mm");
private Segment buildAllSegmentInfo(DependencyReport report) {
Segment result = new Segment();
Map<Integer, Segment> segments = report.getSegments();
DependencyReportMerger merger = new DependencyReportMerger(null);
......@@ -87,24 +94,40 @@ public class Handler implements PageHandler<Context> {
return result;
}
private void buildGraphByEvent(TopologyGraph graph, Map<String, List<Event>> events) {
for (Entry<String, List<Event>> entry : events.entrySet()) {
List<Event> eventList = entry.getValue();
private void buildDashboardErrorInfo(DashboardGraph dashboardGraph, Model model, Payload payload) {
Map<String, List<Node>> nodes = dashboardGraph.getNodes();
Date reportTime = new Date(payload.getDate() + TimeUtil.ONE_MINUTE * model.getMinute());
for (Event event : eventList) {
Node node = graph.findNode(event.getDomain());
for (Entry<String, List<Node>> entry : nodes.entrySet()) {
for (Node node : entry.getValue()) {
String domain = node.getId();
List<Event> events = m_eventManager.queryEvents(domain, reportTime);
if (node != null) {
String des = node.getDes();
des = "</br>" + m_sdf.format(event.getDate()) + " " + event.getSubject();
node.setLink(buildLink(payload, model, domain));
node.setDes(des);
if (events != null && events.size() > 0) {
if (node.getStatus() == GraphConstrant.OK) {
node.setStatus(GraphConstrant.OP_ERROR);
}
node.setDes(node.getDes() + buildZabbixHeader(payload, model));
StringBuilder sb = new StringBuilder();
for (Event event : events) {
sb.append(m_sdf.format(event.getDate())).append((" "));
sb.append(event.getSubject()).append(GraphConstrant.ENTER);
}
node.setDes(node.getDes() + sb.toString());
}
if (node.getStatus() != GraphConstrant.OK) {
String exceptionInfo = buildProblemInfo(domain, payload);
node.setDes(node.getDes() + exceptionInfo);
}
}
}
}
private void buildGraphExtraInfo(Payload payload, Model model, TopologyGraph graph) {
private void buildExceptionInfoOnGraph(Payload payload, Model model, TopologyGraph graph) {
if (graph.getStatus() != GraphConstrant.OK) {
String problemInfo = buildProblemInfo(graph.getId(), payload);
......@@ -123,6 +146,44 @@ public class Handler implements PageHandler<Context> {
}
}
private void buildExternalErrorOnGraph(TopologyGraph graph, String zabbixHeader, Map<String, List<Event>> events) {
for (Entry<String, List<Event>> entry : events.entrySet()) {
List<Event> eventList = entry.getValue();
for (Event event : eventList) {
Node node = graph.findNode(event.getDomain());
if (node != null) {
if (!m_nodes.contains(node.getId())) {
node.setDes(node.getDes() + zabbixHeader);
m_nodes.add(node.getId());
}
if (node.getStatus() == GraphConstrant.OK) {
node.setStatus(GraphConstrant.OP_ERROR);
}
String des = node.getDes();
des = des + m_sdf.format(event.getDate()) + " " + event.getSubject() + GraphConstrant.ENTER;
node.setDes(des);
} else if (event.getDomain().equals(graph.getId())) {
if (!m_nodes.contains(graph.getId())) {
graph.setDes(graph.getDes() + zabbixHeader);
m_nodes.add(graph.getId());
}
if (graph.getStatus() == GraphConstrant.OK) {
graph.setStatus(GraphConstrant.OP_ERROR);
}
String des = graph.getDes();
des = des + m_sdf.format(event.getDate()) + " " + event.getSubject() + GraphConstrant.ENTER;
graph.setDes(des);
}
}
}
}
private List<String> buildGraphList(List<LineChart> charts) {
List<String> result = new ArrayList<String>();
......@@ -154,23 +215,14 @@ public class Handler implements PageHandler<Context> {
}
private void buildHourlyReport(DependencyReport report, Model model, Payload payload) {
Date reportTime = new Date(payload.getDate() + TimeUtil.ONE_MINUTE * model.getMinute());
Segment segment = report.findSegment(model.getMinute());
model.setReport(report);
model.setSegment(segment);
if (payload.isAll()) {
model.setSegment(buildAllSegment(report));
model.setSegment(buildAllSegmentInfo(report));
}
model.setEvents(queryDependencyEvent(segment, payload.getDomain(), reportTime));
}
private TopologyGraph buildHourlyTopologyGraph(Model model, Payload payload) {
long time = payload.getDate() + TimeUtil.ONE_MINUTE * computeMinute(payload);
String domain = payload.getDomain();
return m_graphManager.buildGraphByDomainTime(domain, time);
}
private String buildLink(Payload payload, Model model, String domain) {
......@@ -187,6 +239,18 @@ public class Handler implements PageHandler<Context> {
return result;
}
private String buildZabbixHeader(Payload payload, Model model) {
StringBuilder sb = new StringBuilder();
long end = payload.getDate() + TimeUtil.ONE_MINUTE * model.getMinute();
sb.append(GraphConstrant.LINE).append(GraphConstrant.ENTER);
sb.append("<span style='color:red'>").append(CatString.ZABBIX_ERROR).append("(")
.append(m_sdf.format(new Date(end - TimeUtil.ONE_MINUTE * 10))).append("-").append(m_sdf.format(end))
.append(")").append("</span>").append(GraphConstrant.ENTER);
return sb.toString();
}
private int computeMinute(Payload payload) {
int minute = 0;
String min = payload.getMinute();
......@@ -216,19 +280,35 @@ public class Handler implements PageHandler<Context> {
normalize(model, payload);
Action action = payload.getAction();
Date reportTime = new Date(payload.getDate() + TimeUtil.ONE_MINUTE * model.getMinute());
DependencyReport report = queryDependencyReport(payload);
switch (action) {
case GRAPH:
buildHourlyReport(report, model, payload);
TopologyGraph graph = buildHourlyTopologyGraph(model, payload);
TopologyGraph topologyGraph = m_graphManager.buildGraphByDomainTime(model.getDomain(), reportTime.getTime());
Map<String, List<String>> graphDependency = parseDependencies(topologyGraph);
Map<String, List<Event>> externalErrors = queryDependencyEvent(graphDependency, model.getDomain(), reportTime);
//buildGraphByEvent(graph, model.getEvents());
//buildGraphExtraInfo(payload, model, graph);
model.setTopologyGraph(new DefaultJsonBuilder().buildJson(graph));
buildHourlyReport(report, model, payload);
model.setEvents(externalErrors);
m_nodes = new HashSet<String>();
buildExternalErrorOnGraph(topologyGraph, buildZabbixHeader(payload, model), externalErrors);
buildExceptionInfoOnGraph(payload, model, topologyGraph);
model.setTopologyGraph(new DefaultJsonBuilder().buildJson(topologyGraph));
break;
case VIEW:
buildHourlyReport(report, model, payload);
buildHourlyLineGraph(report, model);
Segment segment = report.findSegment(model.getMinute());
Map<String, List<String>> dependency = parseDependencies(segment);
model.setEvents(queryDependencyEvent(dependency, model.getDomain(), reportTime));
break;
case DASHBOARD:
DashboardGraph dashboardGraph = m_graphManager.buildDashboardGraph(reportTime.getTime());
buildDashboardErrorInfo(dashboardGraph, model, payload);
model.setDashboardGraph(dashboardGraph.toJson());
break;
}
m_jspViewer.view(ctx, model);
......@@ -258,7 +338,6 @@ public class Handler implements PageHandler<Context> {
private Map<String, List<String>> parseDependencies(Segment segment) {
Map<String, List<String>> results = new TreeMap<String, List<String>>();
if (segment != null) {
Map<String, Dependency> dependencies = segment.getDependencies();
......@@ -278,10 +357,28 @@ public class Handler implements PageHandler<Context> {
return results;
}
private Map<String, List<Event>> queryDependencyEvent(Segment segment, String domain, Date date) {
private Map<String, List<String>> parseDependencies(TopologyGraph graph) {
Map<String, List<String>> dependencies = new HashMap<String, List<String>>();
Map<String, Edge> edges = graph.getEdges();
for (Edge temp : edges.values()) {
String type = temp.getType();
String target = temp.getTarget();
List<String> targets = dependencies.get(type);
if (targets == null) {
targets = new ArrayList<String>();
dependencies.put(type, targets);
}
targets.add(target);
}
return dependencies;
}
private Map<String, List<Event>> queryDependencyEvent(Map<String, List<String>> dependencies, String domain,
Date date) {
Map<String, List<Event>> result = new LinkedHashMap<String, List<Event>>();
Map<String, List<String>> dependencies = parseDependencies(segment);
List<Event> domainEvents = m_manager.queryEvents(domain, date);
List<Event> domainEvents = m_eventManager.queryEvents(domain, date);
if (domainEvents != null && domainEvents.size() > 0) {
result.put(domain, domainEvents);
......@@ -291,7 +388,7 @@ public class Handler implements PageHandler<Context> {
List<String> targets = entry.getValue();
for (String temp : targets) {
List<Event> queryEvents = m_manager.queryEvents(temp, date);
List<Event> queryEvents = m_eventManager.queryEvents(temp, date);
if (queryEvents != null && queryEvents.size() > 0) {
List<Event> events = result.get(key);
......
......@@ -5,6 +5,8 @@ public enum JspFile {
GRAPH("/jsp/report/dependencyTopologyGraph.jsp"),
DASHBOARD("/jsp/report/dependencyDashboard.jsp"),
;
private String m_path;
......
......@@ -14,6 +14,8 @@ public class JspViewer extends BaseJspViewer<ReportPage, Action, Context, Model>
return JspFile.VIEW.getPath();
case GRAPH:
return JspFile.GRAPH.getPath();
case DASHBOARD:
return JspFile.DASHBOARD.getPath();
}
throw new RuntimeException("Unknown action: " + action);
......
......@@ -35,6 +35,16 @@ public class Model extends AbstractReportModel<Action, Context> {
private List<String> m_indexGraph;
private Map<String, List<String>> m_dependencyGraph;
private String m_dashboardGraph;
public String getDashboardGraph() {
return m_dashboardGraph;
}
public void setDashboardGraph(String dashboardGraph) {
m_dashboardGraph = dashboardGraph;
}
public List<String> getIndexGraph() {
return m_indexGraph;
......
package com.dianping.cat.report.page.dependency.dashboard;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
public class DashboardConfig implements Initializable {
private Map<String, Group> m_groups = new LinkedHashMap<String, Group>();
private Set<String> m_allDomains = new HashSet<String>();
public boolean contains(String domain){
return m_allDomains.contains(domain);
}
public Map<String, Group> getGroups() {
return m_groups;
}
@Override
public void initialize() throws InitializationException {
addDomain("TuanGou", "TuanGouWeb");
addDomain("TuanGou", "TuanGouApi");
addDomain("TuanGou", "TuanGouRemote");
addDomain("TuanGou", "TuanGouApiMobile");
addDomain("TuanGou", "DealService");
addDomain("TuanGou2", "tuangou-paygate");
addDomain("TuanGou2", "TuanGouWap");
addDomain("TuanGou2", "BCTuangouWeb");
addDomain("TuanGou2", "Unipay");
addDomain("TuanGou3", "PayChannel");
addDomain("TuanGou3", "PayEngine");
addDomain("TuanGou3", "PayOrder");
addDomain("TuanGou3", "BCTuangouServer");
addDomain("TuanGou4", "TuanGouMT");
addDomain("TuanGou4", "TuanGouTracking");
addDomain("TuanGou4", "TuanGouOperation");
}
private void addDomain(String group, String domain) {
Group g = m_groups.get(group);
if (g == null) {
g = new Group();
m_groups.put(group, g);
}
g.addDomain(domain);
m_allDomains.add(domain);
}
public static class Group {
private String m_name;
private List<String> m_domains = new ArrayList<String>();
public Group addDomain(String domain) {
m_domains.add(domain);
return this;
}
public String getName() {
return m_name;
}
public void setName(String name) {
m_name = name;
}
public List<String> getDomains() {
return m_domains;
}
public void setDomains(List<String> domains) {
m_domains = domains;
}
}
}
package com.dianping.cat.report.page.dependency.dashboard;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import com.dianping.cat.home.dependency.graph.entity.Node;
import com.dianping.cat.home.dependency.graph.entity.Edge;
import com.google.gson.Gson;
public class DashboardGraph {
private Map<String, List<Node>> productLines = new LinkedHashMap<String, List<Node>>();
private List<Edge> edges = new ArrayList<Edge>();
private transient Map<String, Node> temp = new LinkedHashMap<String, Node>();
public String toJson() {
return new Gson().toJson(this);
}
public boolean exsit(Node node) {
return temp.containsKey(node.getId());
}
public DashboardGraph addNode(String productLine, Node node) {
List<Node> nodeList = productLines.get(productLine);
if (nodeList == null) {
nodeList = new ArrayList<Node>();
productLines.put(productLine, nodeList);
}
nodeList.add(node);
return this;
}
public DashboardGraph addEdge(Edge edge) {
edges.add(edge);
return this;
}
public Map<String, List<Node>> getNodes() {
return productLines;
}
public List<Edge> getEdges() {
return edges;
}
}
......@@ -11,8 +11,12 @@ public class GraphConstrant {
public static int ERROR = 3;
public static int OP_ERROR = 4;
public static final String DELIMITER = " ";
public static final String ENTER = "<br/>";
public static final String LINE = "###############################################";
}
package com.dianping.cat.report.page.dependency.graph;
import java.util.HashMap;
import java.util.Map;
import org.unidal.helper.Threads.Task;
import org.unidal.lookup.annotation.Inject;
import com.dianping.cat.consumer.problem.model.entity.ProblemReport;
import com.dianping.cat.report.page.model.spi.ModelService;
public class ProblemReportManager {
@Inject(type = ModelService.class, value = "problem")
private ModelService<ProblemReport> m_service;
private Map<String, String> m_exceptionInfos = new HashMap<String, String>();
public class Reload implements Task {
@Override
public void run() {
}
@Override
public String getName() {
return "ExceptionInfoReload";
}
@Override
public void shutdown() {
}
}
}
......@@ -16,13 +16,18 @@ import org.unidal.helper.Threads.Task;
import org.unidal.lookup.annotation.Inject;
import com.dianping.cat.Cat;
import com.dianping.cat.configuration.ServerConfigManager;
import com.dianping.cat.consumer.dependency.model.entity.DependencyReport;
import com.dianping.cat.home.dependency.graph.transform.BaseVisitor;
import com.dianping.cat.helper.TimeUtil;
import com.dianping.cat.home.dependency.graph.entity.Edge;
import com.dianping.cat.home.dependency.graph.entity.Node;
import com.dianping.cat.home.dependency.graph.entity.TopologyGraph;
import com.dianping.cat.message.Message;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.report.page.dependency.dashboard.DashboardConfig;
import com.dianping.cat.report.page.dependency.dashboard.DashboardConfig.Group;
import com.dianping.cat.report.page.dependency.dashboard.DashboardGraph;
import com.dianping.cat.report.page.model.spi.ModelPeriod;
import com.dianping.cat.report.page.model.spi.ModelRequest;
import com.dianping.cat.report.page.model.spi.ModelResponse;
......@@ -37,34 +42,68 @@ public class TopologyGraphManager implements Initializable, LogEnabled {
@Inject
private TopologyGraphBuilder m_graphBuilder;
@Inject
private ServerConfigManager m_manager;
@Inject
private DashboardConfig m_dashboardConfig;
private Map<Long, TopologyGraph> m_topologyGraphs = new ConcurrentHashMap<Long, TopologyGraph>(360);
private Logger m_logger;
private static final String DEPENDENCY = "Dependency";
public TopologyGraph buildGraphByDomainTime(String domain, long time) {
TopologyGraph graph = m_topologyGraphs.get(time);
TopologyGraph result = new TopologyGraph();
long current = System.currentTimeMillis();
long minute = current - current % TimeUtil.ONE_MINUTE;
public DashboardGraph buildDashboardGraph(long time) {
TopologyGraph topologyGraph = queryGraph(time);
DashboardGraph dashboardGraph = new DashboardGraph();
if (minute == time && graph == null) {
graph = m_topologyGraphs.get(time - TimeUtil.ONE_MINUTE);
if (topologyGraph != null) {
Map<String, Group> groups = m_dashboardConfig.getGroups();
for (Entry<String, Group> entry : groups.entrySet()) {
String groupName = entry.getKey();
Group groupDetail = entry.getValue();
for (String nodeName : groupDetail.getDomains()) {
Node node = topologyGraph.findNode(nodeName);
if (node != null) {
dashboardGraph.addNode(groupName, m_graphBuilder.cloneNode(node));
}
}
}
Map<String, Edge> edges = topologyGraph.getEdges();
for (Edge edge : edges.values()) {
String self = edge.getSelf();
String to = edge.getTarget();
if (m_dashboardConfig.contains(self) && m_dashboardConfig.contains(to)) {
dashboardGraph.addEdge(m_graphBuilder.cloneEdge(edge));
}
}
}
result.setId(domain);
result.setType(GraphConstrant.PROJECT);
result.setStatus(GraphConstrant.OK);
return dashboardGraph;
}
if (graph != null) {
Node node = graph.findNode(domain);
public TopologyGraph buildGraphByDomainTime(String domain, long time) {
TopologyGraph all = queryGraph(time);
TopologyGraph topylogyGraph = new TopologyGraph();
topylogyGraph.setId(domain);
topylogyGraph.setType(GraphConstrant.PROJECT);
topylogyGraph.setStatus(GraphConstrant.OK);
if (all != null) {
Node node = all.findNode(domain);
if (node != null) {
result.setDes(node.getDes());
result.setStatus(node.getStatus());
result.setType(node.getType());
topylogyGraph.setDes(node.getDes());
topylogyGraph.setStatus(node.getStatus());
topylogyGraph.setType(node.getType());
}
Collection<Edge> edges = graph.getEdges().values();
Collection<Edge> edges = all.getEdges().values();
for (Edge edge : edges) {
String self = edge.getSelf();
......@@ -72,31 +111,41 @@ public class TopologyGraphManager implements Initializable, LogEnabled {
Edge cloneEdge = m_graphBuilder.cloneEdge(edge);
if (self.equals(domain)) {
Node other = graph.findNode(target);
Node other = all.findNode(target);
if (other != null) {
result.addNode(m_graphBuilder.cloneNode(other));
topylogyGraph.addNode(m_graphBuilder.cloneNode(other));
} else {
result.addNode(m_graphBuilder.createNode(target));
topylogyGraph.addNode(m_graphBuilder.createNode(target));
}
edge.setOpposite(false);
result.addEdge(cloneEdge);
topylogyGraph.addEdge(cloneEdge);
} else if (target.equals(domain)) {
Node other = graph.findNode(self);
Node other = all.findNode(self);
if (other != null) {
result.addNode(m_graphBuilder.cloneNode(other));
topylogyGraph.addNode(m_graphBuilder.cloneNode(other));
} else {
result.addNode(m_graphBuilder.createNode(target));
topylogyGraph.addNode(m_graphBuilder.createNode(target));
}
cloneEdge.setTarget(edge.getSelf());
cloneEdge.setSelf(edge.getTarget());
cloneEdge.setOpposite(true);
result.addEdge(cloneEdge);
topylogyGraph.addEdge(cloneEdge);
}
}
}
return result;
return topylogyGraph;
}
private TopologyGraph queryGraph(long time) {
TopologyGraph graph = m_topologyGraphs.get(time);
long current = System.currentTimeMillis();
long minute = current - current % TimeUtil.ONE_MINUTE;
if (minute == time && graph == null) {
graph = m_topologyGraphs.get(time - TimeUtil.ONE_MINUTE);
}
return graph;
}
@Override
......@@ -106,7 +155,9 @@ public class TopologyGraphManager implements Initializable, LogEnabled {
@Override
public void initialize() throws InitializationException {
// if(!m_manager.isLocalMode()&&m_manager.isJobMachine()){
Threads.forGroup("Cat").start(new Reload());
// }
}
private class Reload implements Task {
......@@ -132,9 +183,9 @@ public class TopologyGraphManager implements Initializable, LogEnabled {
}
private List<DependencyReport> fetchReport(Collection<String> domains) {
List<DependencyReport> reports = new ArrayList<DependencyReport>();
long current = System.currentTimeMillis();
long currentHour = current - current % TimeUtil.ONE_HOUR;
List<DependencyReport> reports = new ArrayList<DependencyReport>();
Transaction t = Cat.newTransaction(DEPENDENCY, "FetchReport");
try {
......
......@@ -66,13 +66,31 @@ public class EventCollectManager implements Initializable, LogEnabled {
return result;
}
public List<Event> findEvents(long date, String domain) {
Map<String, List<Event>> domainEvent = m_events.get(date);
if (domainEvent == null) {
return null;
} else {
List<Event> result = domainEvent.get(domain);
if (result == null) {
return null;
} else {
return result;
}
}
}
private List<Event> queryEventsByMemory(String domain, Date date, int minute) {
List<Event> result = new ArrayList<Event>();
long time = date.getTime();
long time = date.getTime() + TimeUtil.ONE_MINUTE - date.getTime() % TimeUtil.ONE_MINUTE;
for (int i = 0; i < minute; i++) {
List<Event> events = findOrCreateEvents(time - minute * TimeUtil.ONE_MINUTE, domain);
result.addAll(events);
List<Event> events = findEvents(time - i * TimeUtil.ONE_MINUTE, domain);
if (events != null) {
result.addAll(events);
}
}
return result;
}
......@@ -93,6 +111,7 @@ public class EventCollectManager implements Initializable, LogEnabled {
long current = System.currentTimeMillis();
if (current - date.getTime() < TimeUtil.ONE_HOUR * 2) {
// return queryEventsByDB(domain, date, 10);
return queryEventsByMemory(domain, date, 10);
} else {
return queryEventsByDB(domain, date, 10);
......@@ -138,10 +157,10 @@ public class EventCollectManager implements Initializable, LogEnabled {
m_eventDao.insert(error);
long date = error.getDate().getTime();
long minute = date - date % TimeUtil.ONE_MINUTE;
String domain = error.getDomain();
long time = date - date % TimeUtil.ONE_MINUTE;
findOrCreateEvents(time, domain).add(error);
findOrCreateEvents(minute, domain).add(error);
}
} catch (InterruptedException e) {
active = false;
......
......@@ -1193,6 +1193,10 @@
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.report.page.dependency.dashboard.DashboardConfig</role>
<implementation>com.dianping.cat.report.page.dependency.dashboard.DashboardConfig</implementation>
</component>
<component>
<role>com.dianping.cat.report.page.dependency.graph.TopologyGraphManager</role>
<implementation>com.dianping.cat.report.page.dependency.graph.TopologyGraphManager</implementation>
......@@ -1200,6 +1204,12 @@
<requirement>
<role>com.dianping.cat.report.page.dependency.graph.TopologyGraphBuilder</role>
</requirement>
<requirement>
<role>com.dianping.cat.configuration.ServerConfigManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.page.dependency.dashboard.DashboardConfig</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.page.model.spi.ModelService</role>
<role-hint>dependency</role-hint>
......@@ -2584,12 +2594,22 @@
<requirement>
<role>com.dianping.cat.report.page.dependency.graph.TopologyGraphBuilder</role>
</requirement>
<requirement>
<role>com.dianping.cat.configuration.ServerConfigManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.report.page.dependency.dashboard.DashboardConfig</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.report.page.dependency.graph.TopologyGraphBuilder</role>
<implementation>com.dianping.cat.report.page.dependency.graph.TopologyGraphBuilder</implementation>
</component>
<component>
<role>com.dianping.cat.report.page.dependency.dashboard.DashboardConfig</role>
<implementation>com.dianping.cat.report.page.dependency.dashboard.DashboardConfig</implementation>
</component>
<component>
<role>com.dianping.cat.report.page.externalError.Handler</role>
<implementation>com.dianping.cat.report.page.externalError.Handler</implementation>
......
......@@ -23,13 +23,14 @@
<div class="row-fluid">
<div class="span12 text-center">
<a class="btn btn-danger btn-primary" href="?op=dependencyGraph&minute=${model.minute}&domain=${model.domain}&date=${model.date}">切换到实时拓扑图</a>
<a class="btn btn-danger btn-primary" href="?op=dashboard&minute=${model.minute}&domain=${model.domain}&date=${model.date}">切换到产品线监控大盘</a>
</div>
</div>
<div class="tabbable text-error" id="content"> <!-- Only required for left/right tabs -->
<ul class="nav nav-tabs">
<li style="margin-left:20px;" class="text-right active"><a href="#tab1" data-toggle="tab">数据趋势</a></li>
<li class="text-right"><a href="#tab2" data-toggle="tab">运维告警</a></li>
<li class="text-right"><a href="#tab3" data-toggle="tab">详细数据</a></li>
<li style="margin-left:20px;" class="text-right active"><a href="#tab1" data-toggle="tab">数据趋势(项目以及依赖项目)</a></li>
<li class="text-right"><a href="#tab2" data-toggle="tab">运维告警(Zabbix告警信息)</a></li>
<li class="text-right"><a href="#tab3" data-toggle="tab">详细数据(Detail以及配置)</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab1">
......@@ -58,6 +59,11 @@
</a:report>
<script type="text/javascript">
$(document).ready(function() {
$('#content .nav-tabs a').mouseenter(function (e) {
e.preventDefault();
$(this).tab('show');
});
$('#minute'+${model.minute}).addClass('disabled');
$('.contents').dataTable({
"sPaginationType": "full_numbers",
......@@ -74,7 +80,7 @@
e.preventDefault();
$(this).tab('show');
});
$('#tab0').addClass('active');
$('#zabbixTab0').addClass('active');
$('#leftTab0').addClass('active');
$('.switch').css('display','none');
$('.dataTables_info').css('display','none');
......
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="a" uri="/WEB-INF/app.tld"%>
<%@ taglib prefix="w" uri="http://www.unidal.org/web/core"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="res" uri="http://www.unidal.org/webres"%>
<jsp:useBean id="ctx" type="com.dianping.cat.report.page.dependency.Context" scope="request"/>
<jsp:useBean id="payload" type="com.dianping.cat.report.page.dependency.Payload" scope="request"/>
<jsp:useBean id="model" type="com.dianping.cat.report.page.dependency.Model" scope="request"/>
<a:report title="Dependency Report"
navUrlPrefix="domain=${model.domain}&op=dependencyGraph">
<jsp:attribute name="subtitle">From ${w:format(model.report.startTime,'yyyy-MM-dd HH:mm:ss')} to ${w:format(model.report.endTime,'yyyy-MM-dd HH:mm:ss')}</jsp:attribute>
<jsp:body>
<res:useCss value='${res.css.local.table_css}' target="head-css" />
<res:useJs value="${res.js.local['jquery.dataTables.min.js']}" target="head-js" />
<res:useJs value="${res.js.local['startopo.js']}" target="head-js" />
<res:useJs value="${res.js.local['raphael-min.js']}" target="head-js" />
<res:useJs value="${res.js.local['dependencyConfig.js']}" target="head-js" />
<res:useJs value="${res.js.local['jquery.validate.min.js']}" target="head-js" />
<div class="report">
<%@ include file="dependencyDashboardNav.jsp"%>
</div>
</jsp:body>
</a:report>
<script type="text/javascript">
$(document).ready(function() {
$('#minute'+${model.minute}).addClass('disabled');
var data = ${model.dashboardGraph};
console.log(data);
function parse(data){
var nodes = data.nodes;
var points = [];
var sides = [];
for(var o in nodes){
if(nodes.hasOwnProperty(o)){
points.push(nodes[o]);
}
}
for(var o in data.edges){
if(data.edges.hasOwnProperty(o)){
sides.push(data.edges[o]);
}
}
data.points = points;
data.sides = sides;
delete data.nodes;
delete data.edges;
return data;
}
new StarTopo('container',parse(data),{
typeMap:{
database:'rect',
project:'circle',
service:'lozenge'
},
colorMap:{
"1":'#2fbf2f',
"2":'#bfa22f',
"3":'#b94a48',
"4":'#772fbf'
},
radius:300,
sideWeight:function(weight){
return weight+1
},
nodeWeight:function(weight){
return weight/5+0.8;
}});
});
</script>
<style>
.pagination{
margin:4px 0;
}
.pagination ul{
margin-top:0px;
}
.pagination ul > li > a, .pagination ul > li > span{
padding:3px 10px;
}
</style>
<%@ page contentType="text/html; charset=utf-8" %>
<div class='text-center'>
<a class="btn btn-danger btn-primary" href="?minute=${model.minute}&domain=${model.domain}&date=${model.date}">切换到实时趋势图(当前分钟:${model.minute})</a>
<c:forEach var="item" items="${model.minutes}" varStatus="status">
<c:if test="${status.index % 30 ==0}">
<div class="pagination">
<ul>
</c:if>
<c:if test="${item > model.maxMinute }"><li class="disabled" id="minute${item}"><a
href="?op=dependencyGraph&domain=${model.domain}&date=${model.date}&minute=${item}">
<c:if test="${item < 10}">0${item}</c:if>
<c:if test="${item >= 10}">${item}</c:if></a></li>
</c:if>
<c:if test="${item <= model.maxMinute }"><li id="minute${item}"><a
href="?op=dependencyGraph&domain=${model.domain}&date=${model.date}&minute=${item}">
<c:if test="${item < 10}">0${item}</c:if>
<c:if test="${item >= 10}">${item}</c:if></a></li>
</c:if>
<c:if test="${status.index % 30 ==29 || status.last}">
</ul>
</div>
</c:if>
</c:forEach>
</div>
\ No newline at end of file
......@@ -2,7 +2,7 @@
<div class="tabbable" id="otherDependency">
<ul class="nav nav-tabs">
<c:forEach var="item" items="${model.events}" varStatus="status" >
<li id="leftTab${status.index}" class="text-right"><a href="#tab${status.index}" data-toggle="tab">
<li id="leftTab${status.index}" class="text-right"><a href="#zabbixTab${status.index}" data-toggle="tab">
${item.key}
<c:set var="size" value="${w:size(item.value)}"/>
<c:if test="${size > 0 }"><span class='text-error'>(${size})</span></c:if>
......@@ -12,7 +12,7 @@
<div class="tab-content">
<c:forEach var="entry" items="${model.events}" varStatus="status" >
<c:set var="items" value="${entry.value}"/>
<div class="tab-pane" id="tab${status.index}">
<div class="tab-pane" id="zabbixTab${status.index}">
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr><th>时间</th>
......
......@@ -20,29 +20,7 @@
<res:useJs value="${res.js.local['jquery.validate.min.js']}" target="head-js" />
<div class="report">
<div class='text-center'>
<a class="btn btn-danger btn-primary" href="?minute=${model.minute}&domain=${model.domain}&date=${model.date}">切换到实时趋势图(当前分钟:${model.minute})</a>
<c:forEach var="item" items="${model.minutes}" varStatus="status">
<c:if test="${status.index % 30 ==0}">
<div class="pagination">
<ul>
</c:if>
<c:if test="${item > model.maxMinute }"><li class="disabled" id="minute${item}"><a
href="?op=dependencyGraph&domain=${model.domain}&date=${model.date}&minute=${item}">
<c:if test="${item < 10}">0${item}</c:if>
<c:if test="${item >= 10}">${item}</c:if></a></li>
</c:if>
<c:if test="${item <= model.maxMinute }"><li id="minute${item}"><a
href="?op=dependencyGraph&domain=${model.domain}&date=${model.date}&minute=${item}">
<c:if test="${item < 10}">0${item}</c:if>
<c:if test="${item >= 10}">${item}</c:if></a></li>
</c:if>
<c:if test="${status.index % 30 ==29 || status.last}">
</ul>
</div>
</c:if>
</c:forEach>
</div>
<%@ include file="dependencyTopologyGraphNav.jsp"%>
<div class="tabbable tabs-left " id="content"> <!-- Only required for left/right tabs -->
<ul class="nav nav-tabs alert-info">
<li style="margin-left:20px;" class="text-right active"><a href="#tab1" data-toggle="tab">依赖拓扑</a></li>
......@@ -72,10 +50,10 @@
$('#content .nav-tabs a').mouseenter(function (e) {
e.preventDefault();
$(this).tab('show');
});
});
$('#minute'+${model.minute}).addClass('disabled');
$('#tab0').addClass('active');
$('#zabbixTab0').addClass('active');
$('#leftTab0').addClass('active');
$('.contents').dataTable({
"sPaginationType": "full_numbers",
......@@ -89,6 +67,7 @@
"bPaginate": false,
});
var data = ${model.topologyGraph};
console.log(data);
function parse(data){
var nodes = data.nodes;
var points = [];
......@@ -119,7 +98,8 @@
colorMap:{
"1":'#2fbf2f',
"2":'#bfa22f',
"3":'#b94a48'
"3":'#b94a48',
"4":'#772fbf'
},
radius:300,
sideWeight:function(weight){
......
<%@ page contentType="text/html; charset=utf-8" %>
<div class='text-center'>
<span class='text-error'><strong>(当前分钟:${model.minute})</strong></span><a class="btn btn-danger btn-primary" href="?minute=${model.minute}&domain=${model.domain}&date=${model.date}">切换到实时趋势图</a>
<a class="btn btn-danger btn-primary" href="?op=dashboard&minute=${model.minute}&domain=${model.domain}&date=${model.date}">切换到产品线监控大盘</a>
<c:forEach var="item" items="${model.minutes}" varStatus="status">
<c:if test="${status.index % 30 ==0}">
<div class="pagination">
<ul>
</c:if>
<c:if test="${item > model.maxMinute }"><li class="disabled" id="minute${item}"><a
href="?op=dependencyGraph&domain=${model.domain}&date=${model.date}&minute=${item}">
<c:if test="${item < 10}">0${item}</c:if>
<c:if test="${item >= 10}">${item}</c:if></a></li>
</c:if>
<c:if test="${item <= model.maxMinute }"><li id="minute${item}"><a
href="?op=dependencyGraph&domain=${model.domain}&date=${model.date}&minute=${item}">
<c:if test="${item < 10}">0${item}</c:if>
<c:if test="${item >= 10}">${item}</c:if></a></li>
</c:if>
<c:if test="${status.index % 30 ==29 || status.last}">
</ul>
</div>
</c:if>
</c:forEach>
</div>
\ No newline at end of file
package com.dianping.cat.demo;
import org.junit.Test;
import com.dianping.cat.Cat;
import com.dianping.cat.message.Transaction;
public class TestChildrenMany {
@Test
public void test() {
Transaction t = Cat.newTransaction("type", "name");
for (int i = 0; i < 1005; i++) {
Cat.logEvent("type", "name");
}
t.complete();
}
}
package com.dianping.cat.report.page.dependency;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Assert;
import org.junit.Test;
import org.unidal.webres.helper.Files;
......@@ -32,51 +26,4 @@ public class DependencyReportMergerTest {
Assert.assertEquals("Check the merge result!", merger.getDependencyReport().toString(), result.toString());
}
@Test
public void testSendError() {
for (int i = 0; i < 10; i++) {
try {
String buildUrl = buildUrl(i);
System.out.println(buildUrl);
URL url = new URL(buildUrl);
URLConnection URLconnection = url.openConnection();
URLconnection.setRequestProperty("User-Agent",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon;)");
URLconnection.setRequestProperty("referer", "http://www.dianping.com/shop/1");
HttpURLConnection httpConnection = (HttpURLConnection) URLconnection;
int responseCode = httpConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
} else {
System.err.println("Error");
}
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private String buildUrl(int i) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String ip = "192.168.7.70";
String title = "ZabbixError";
String database = "cat";
String content = "ZabbixErrorContent";
String time = sdf.format(new Date());
int type = i % 3 + 1;
StringBuilder sb = new StringBuilder(128);
sb.append("http://localhost:2281/cat/r/externalError?");
sb.append("ip=" + ip);
sb.append("&title=" + title);
sb.append("&database=" + database);
sb.append("&content=" + content);
sb.append("&link=" + "http://www.sina.com.cn");
sb.append("&time=" + time);
sb.append("&type=" + type);
return sb.toString();
}
}
package com.dianping.cat.report.page.externalError;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Test;
public class ExternalErrorTest {
@Test
public void testSendError() {
for (int i = 0; i < 10; i++) {
try {
String buildUrl = buildUrl(i);
System.out.println(buildUrl);
URL url = new URL(buildUrl);
URLConnection URLconnection = url.openConnection();
URLconnection.setRequestProperty("User-Agent",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon;)");
URLconnection.setRequestProperty("referer", "http://www.dianping.com/shop/1");
HttpURLConnection httpConnection = (HttpURLConnection) URLconnection;
int responseCode = httpConnection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
} else {
System.err.println("Error");
}
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private String buildUrl(int i) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String ip = "192.168.7.70";
String title = "ZabbixError";
String database = "cat";
String content = "ZabbixErrorContent";
String time = sdf.format(new Date());
int type = i % 3 + 1;
StringBuilder sb = new StringBuilder(128);
sb.append("http://localhost:2281/cat/r/externalError?");
sb.append("ip=" + ip);
sb.append("&title=" + title);
sb.append("&database=" + database);
sb.append("&content=" + content);
sb.append("&link=" + "http://www.sina.com.cn");
sb.append("&time=" + time);
sb.append("&type=" + type);
return sb.toString();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册