[유치수] [PINPOINT-27] 서버 맵에 필터 기능 추가.

git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-web/trunk@1609 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
Chisu Yu
2013-05-06 05:56:06 +00:00
parent 5d88afc1cf
commit f49d8690d2
6 changed files with 199 additions and 4 deletions
@@ -1,5 +1,7 @@
package com.nhn.hippo.web.controller;
import java.util.Set;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
@@ -10,7 +12,10 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.nhn.hippo.web.applicationmap.ApplicationMap;
import com.nhn.hippo.web.calltree.server.ServerCallTree;
import com.nhn.hippo.web.service.ApplicationMapService;
import com.nhn.hippo.web.service.FlowChartService;
import com.nhn.hippo.web.vo.TraceId;
/**
*
@@ -18,10 +23,13 @@ import com.nhn.hippo.web.service.ApplicationMapService;
*/
@Controller
public class ApplicationMapController extends BaseController {
@Autowired
private ApplicationMapService applicationMapService;
@Autowired
private FlowChartService flow;
@RequestMapping(value = "/getServerMapData2", method = RequestMethod.GET)
public String getServerMapData2(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("serviceType") short serviceType, @RequestParam("from") long from, @RequestParam("to") long to) {
ApplicationMap map = applicationMapService.selectApplicationMap(applicationName, serviceType, from, to);
@@ -39,4 +47,19 @@ public class ApplicationMapController extends BaseController {
long from = to - period;
return getServerMapData2(model, response, applicationName, serviceType, from, to);
}
@RequestMapping(value = "/getFilteredServerMapData", method = RequestMethod.GET)
public String getFilteredServerMapData(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("serviceType") short serviceType, @RequestParam("from") long from, @RequestParam("to") long to) {
Set<TraceId> traceIdSet = flow.selectTraceIdsFromApplicationTraceIndex(applicationName, from, to);
System.out.println(traceIdSet);
ServerCallTree map = flow.selectServerCallTree(traceIdSet);
model.addAttribute("nodes", map.getNodes());
model.addAttribute("links", map.getLinks());
addResponseHeader(response);
return "applicationmap.filtered";
}
}
@@ -18,6 +18,8 @@ public interface TraceDao {
// TODO list하고 set하고 비교해서 하나 없애야 될듯 하다.
List<List<SpanBo>> selectSpans(List<TraceId> traceIdList);
List<List<SpanBo>> selectAllSpans(Set<TraceId> traceIdSet);
List<List<SpanBo>> selectSpans(Set<TraceId> traceIdSet);
@@ -71,6 +71,18 @@ public class HbaseTraceDao implements TraceDao {
}
return template2.get(HBaseTables.TRACES, gets, spanMapper);
}
@Override
public List<List<SpanBo>> selectAllSpans(Set<TraceId> traceIdSet) {
List<Get> gets = new ArrayList<Get>(traceIdSet.size());
for (TraceId traceId : traceIdSet) {
Get get = new Get(traceId.getBytes());
get.addFamily(HBaseTables.TRACES_CF_SPAN);
get.addFamily(HBaseTables.TRACES_CF_TERMINALSPAN);
gets.add(get);
}
return template2.get(HBaseTables.TRACES, gets, spanMapper);
}
@Override
public List<SpanBo> selectSpans(TraceId traceId) {
@@ -20,4 +20,6 @@ public interface FlowChartService {
public ServerCallTree selectServerCallTree(TraceId traceId);
public BusinessTransactions selectBusinessTransactions(Set<TraceId> traceIds, String applicationName, long from, long to);
public ServerCallTree selectServerCallTree(Set<TraceId> traceIdSet);
}
@@ -12,6 +12,8 @@ import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
import com.nhn.hippo.web.calltree.server.AgentIdNodeSelector;
import com.nhn.hippo.web.calltree.server.ApplicationIdNodeSelector;
import com.nhn.hippo.web.calltree.server.NodeSelector;
import com.nhn.hippo.web.calltree.server.ServerCallTree;
import com.nhn.hippo.web.dao.ApplicationIndexDao;
import com.nhn.hippo.web.dao.ApplicationTraceIndexDao;
@@ -57,7 +59,7 @@ public class FlowChartServiceImpl implements FlowChartService {
List<SpanBo> transaction = this.traceDao.selectSpans(traceId);
Set<String> endPoints = createUniqueEndpoint(transaction);
ServerCallTree tree = createServerCallTree(transaction);
ServerCallTree tree = createServerCallTree(transaction, new AgentIdNodeSelector());
// subSpan에서 record할 데이터만 골라낸다.
List<SpanEventBo> spanEventBoList = findRecordStatisticsSpanEventData(transaction, endPoints);
@@ -70,6 +72,37 @@ public class FlowChartServiceImpl implements FlowChartService {
return tree;
}
/**
* filtered application map
*/
@Override
public ServerCallTree selectServerCallTree(Set<TraceId> traceIdSet) {
StopWatch watch = new StopWatch();
watch.start();
List<List<SpanBo>> transactionList = this.traceDao.selectAllSpans(traceIdSet);
List<SpanBo> transaction = new ArrayList<SpanBo>();
for (List<SpanBo> t : transactionList) {
for (SpanBo span : t) {
transaction.add(span);
}
}
Set<String> endPoints = createUniqueEndpoint(transaction);
ServerCallTree tree = createServerCallTree(transaction, new ApplicationIdNodeSelector());
// subSpan에서 record할 데이터만 골라낸다.
List<SpanEventBo> spanEventBoList = findRecordStatisticsSpanEventData(transaction, endPoints);
tree.addSpanEventList(spanEventBoList);
tree.build();
watch.stop();
logger.info("Fetch single transaction serverCallTree elapsed. {}ms", watch.getLastTaskTimeMillis());
return tree;
}
private List<SpanEventBo> findRecordStatisticsSpanEventData(List<SpanBo> transaction, Set<String> endPoints) {
List<SpanEventBo> filterSpanEventBo = new ArrayList<SpanEventBo>();
@@ -102,8 +135,8 @@ public class FlowChartServiceImpl implements FlowChartService {
* @param transaction
* @return
*/
private ServerCallTree createServerCallTree(List<SpanBo> transaction) {
ServerCallTree serverCallTree = new ServerCallTree(new AgentIdNodeSelector());
private ServerCallTree createServerCallTree(List<SpanBo> transaction, NodeSelector nodeSelector) {
ServerCallTree serverCallTree = new ServerCallTree(nodeSelector);
serverCallTree.addSpanList(transaction);
// TODO 이 메소드는 transaction하나만 조회하는 페이지에서 사용되기 때문에 이렇게 한다.
@@ -0,0 +1,123 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="hippo" uri="http://hippo.nhncorp.com/hippo" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title>Transaction details (${traceId})</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/common/css/bootstrap/bootstrap.css" rel="stylesheet">
<link href="/common/css/bootstrap/bootstrap-responsive.css" rel="stylesheet"/>
<link href="/common/css/hippo/hippo.css" rel="stylesheet"/>
<link href="/common/css/hippo/sorttable.css" rel="stylesheet"/>
<link href="/common/css/hippo/scatter.css" rel="stylesheet"/>
<link href="/common/css/datepicker.css" rel="stylesheet"/>
<link href="/select2/select2-customized.css" rel="stylesheet"/>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- commons -->
<script type="text/javascript" src="/common/js/jquery/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="/common/js/jquery/jquery-ui-1.10.2.js"></script>
<script type="text/javascript" src="/common/js/bootstrap.min.js"></script>
<script type="text/javascript" src="/common/js/bootstrap-datepicker.js"></script>
<script type="text/javascript" src="/common/js/modernizr-2.6.2.min.js"></script>
<script type="text/javascript" src="/common/js/date.js"></script>
<script type="text/javascript" src="/common/js/hippo/scatter/underscore-min.js"></script>
<script type="text/javascript" src="/common/js/hippo/scatter/jquery.Class.js"></script>
<script type="text/javascript" src="/common/js/hippo/hippo.js"></script>
<script type="text/javascript" src="/common/js/sorttable.js"></script>
<script type="text/javascript" src="/select2/select2.js"></script>
<!-- scatter chart -->
<script type="text/javascript" src="/common/js/hippo/chart-scatter4.js"></script>
<script type="text/javascript" src="/common/js/hippo/scatter/jquery.dragToSelect.js"></script>
<script type="text/javascript" src="/common/js/hippo/scatter/jquery.BigScatterChart.js"></script>
<!-- server map -->
<script type="text/javascript" src="/common/js/hippo/chart-servermap.js"></script>
<script type="text/javascript" src="/common/js/go.js"></script>
<script type="text/javascript" src="/common/js/hippo/servermap/jquery.tmpl.min.js"></script>
<script type="text/javascript" src="/common/js/hippo/servermap/Point2D.js"></script>
<script type="text/javascript" src="/common/js/hippo/servermap/intersection.js"></script>
<script type="text/javascript" src="/common/js/hippo/servermap/canvas.roundRect.js"></script>
<script type="text/javascript" src="/common/js/hippo/servermap/jquery.ServerMap.js"></script>
<!-- help -->
<script type="text/javascript" src="/common/js/hippo/help.js"></script>
<script type="text/javascript" src="/common/js/hippo/message.js"></script>
</head>
<body>
<div id="servermap" style="width:1000px;height:700px; border:1px solid #DDDDDD; overflow:hidden;"></div>
<script type="text/javascript">
var data = {
"applicationMapData" : {
"nodeDataArray": [
<c:forEach items="${nodes}" var="node" varStatus="status">
{
"id" : ${status.count},
"key" : ${status.count},
"text" : "${node}",
"hosts" : [
<c:forEach items="${node.hosts}" var="host" varStatus="status2">
"${host}"
<c:if test="${!status2.last}">,</c:if>
</c:forEach>
],
"category" : "${node.serviceType.desc}",
"terminal" : "${node.serviceType.terminal}"
} <c:if test="${!status.last}">,</c:if>
</c:forEach>
],
"linkDataArray": [
<c:forEach items="${links}" var="link" varStatus="status">
{
"id" : "${link.from.sequence + 1}-${link.to.sequence + 1}",
"from" : ${link.from.sequence + 1},
"to" : ${link.to.sequence + 1},
"text" : ${link.histogram.totalCount},
"error" : ${link.histogram.errorCount},
"slow" : ${link.histogram.slowCount},
"histogram" : ${link.histogram}
} <c:if test="${!status.last}">,</c:if>
</c:forEach>
]
}
}
var oServerMap;
$(document).ready(function () {
var containerId = "servermap";
if (data.applicationMapData.nodeDataArray.length == 0) {
return;
}
if (oServerMap == null) {
oServerMap = new ServerMap({
sContainerId : containerId,
fOnNodeClick : function(e, data) {
// nodeClickHandler(e, data, "#" + containerId);
},
fOnLinkClick : function(e, data) {
// linkClickHandler(e, data, "#" + containerId);
}
});
}
oServerMap.load(data.applicationMapData);
$('#chartTabs a:first').tab('show');
$('#traceTabs a:first').tab('show');
});
</script>
</body>
</html>