mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-17 08:46:22 +10:00
[유치수] [NOBTS] refactoring.
git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-web/trunk@1564 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
@@ -1,24 +1,16 @@
|
||||
package com.nhn.hippo.web.controller;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -26,12 +18,7 @@ import com.nhn.hippo.web.vo.TraceId;
|
||||
*/
|
||||
@Controller
|
||||
public class ApplicationMapController extends BaseController {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private FlowChartService flow;
|
||||
|
||||
|
||||
@Autowired
|
||||
private ApplicationMapService applicationMapService;
|
||||
|
||||
@@ -52,64 +39,4 @@ public class ApplicationMapController extends BaseController {
|
||||
long from = to - period;
|
||||
return getServerMapData2(model, response, applicationName, serviceType, from, to);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/getServerMapData", method = RequestMethod.GET)
|
||||
public String getServerMapData(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("from") long from, @RequestParam("to") long to) {
|
||||
// TODO 제거 하거나, interceptor로 할것.
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start("scanTraceindex");
|
||||
|
||||
Set<TraceId> traceIdList = flow.selectTraceIdsFromApplicationTraceIndex(applicationName, from, to);
|
||||
|
||||
watch.stop();
|
||||
logger.info("Fetch traceIdList elapsed : {}ms, {} traces", watch.getLastTaskTimeMillis(), traceIdList.size());
|
||||
watch.start("selectServerCallTree");
|
||||
|
||||
ServerCallTree callTree = flow.selectServerCallTree(traceIdList, applicationName, from, to);
|
||||
|
||||
watch.stop();
|
||||
logger.info("Fetch calltree time : {}ms", watch.getLastTaskTimeMillis());
|
||||
|
||||
model.addAttribute("nodes", callTree.getNodes());
|
||||
model.addAttribute("links", callTree.getLinks());
|
||||
|
||||
addResponseHeader(response);
|
||||
|
||||
return "servermap";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/getLastServerMapData", method = RequestMethod.GET)
|
||||
public String getLastServerMapData(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("period") long period) {
|
||||
long to = getQueryEndTime();
|
||||
long from = to - period;
|
||||
return getServerMapData(model, response, applicationName, from, to);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@RequestMapping(value = "/flowserverByHost", method = RequestMethod.GET)
|
||||
public String flowServerByHost(Model model, @RequestParam("host") String[] hosts, @RequestParam("from") long from, @RequestParam("to") long to) {
|
||||
String[] agentIds = flow.selectAgentIds(hosts);
|
||||
|
||||
// TODO 제거 하거나, interceptor로 할것.
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start("scanTraceindex");
|
||||
|
||||
Set<TraceId> traceIds = flow.selectTraceIdsFromTraceIndex(agentIds, from, to);
|
||||
|
||||
watch.stop();
|
||||
logger.info("time:{} {}", watch.getLastTaskTimeMillis(), traceIds.size());
|
||||
watch.start("selectServerCallTree");
|
||||
|
||||
ServerCallTree callTree = flow.selectServerCallTree(traceIds);
|
||||
|
||||
watch.stop();
|
||||
logger.info("time:{}", watch.getLastTaskTimeMillis());
|
||||
|
||||
model.addAttribute("nodes", callTree.getNodes());
|
||||
model.addAttribute("links", callTree.getLinks());
|
||||
|
||||
logger.debug("callTree:{}", callTree);
|
||||
|
||||
return "flowserver";
|
||||
}
|
||||
}
|
||||
@@ -80,13 +80,20 @@ public class BusinessTransactionController extends BaseController {
|
||||
return getBusinessTransactionsData(model, response, applicationName, from, to);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/selectTransaction", method = RequestMethod.GET)
|
||||
public ModelAndView selectTransaction(@RequestParam("traceId") String traceIdParam, @RequestParam("focusTimestamp") long focusTimestamp) {
|
||||
/**
|
||||
* 선택한 하나의 Transaction 정보 조회.
|
||||
*
|
||||
* @param traceIdParam
|
||||
* @param focusTimestamp
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/transactionInfo", method = RequestMethod.GET)
|
||||
public ModelAndView transactionInfo(@RequestParam("traceId") String traceIdParam, @RequestParam("focusTimestamp") long focusTimestamp) {
|
||||
logger.debug("traceId:{}", traceIdParam);
|
||||
|
||||
final TraceId traceId = new TraceId(traceIdParam);
|
||||
|
||||
ModelAndView mv = new ModelAndView("selectTransaction");
|
||||
ModelAndView mv = new ModelAndView("transactionInfo");
|
||||
|
||||
try {
|
||||
// select spans
|
||||
|
||||
@@ -15,9 +15,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import com.nhn.hippo.web.service.FlowChartService;
|
||||
import com.nhn.hippo.web.service.SpanService;
|
||||
import com.nhn.hippo.web.vo.RequestMetadataQuery;
|
||||
import com.nhn.hippo.web.service.ScatterChartService;
|
||||
import com.nhn.hippo.web.vo.TransactionMetadataQuery;
|
||||
import com.nhn.hippo.web.vo.scatter.Dot;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
|
||||
@@ -31,10 +30,7 @@ public class ScatterChartController extends BaseController {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private FlowChartService flow;
|
||||
|
||||
@Autowired
|
||||
private SpanService spanService;
|
||||
private ScatterChartService scatter;
|
||||
|
||||
@RequestMapping(value = "/scatterpopup", method = RequestMethod.GET)
|
||||
public String scatterPopup(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("from") long from, @RequestParam("to") long to, @RequestParam("period") long period, @RequestParam("usePeriod") boolean usePeriod) {
|
||||
@@ -45,29 +41,6 @@ public class ScatterChartController extends BaseController {
|
||||
model.addAttribute("usePeriod", usePeriod);
|
||||
return "scatterPopup";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/scatterView", method = RequestMethod.GET)
|
||||
public String getScatterView(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("from") long from, @RequestParam("to") long to, @RequestParam("limit") int limit) {
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start("selectScatterData");
|
||||
|
||||
List<Dot> scatterData = flow.selectScatterData(applicationName, from, to, limit);
|
||||
watch.stop();
|
||||
|
||||
logger.info("Fetch scatterData time : {}ms", watch.getLastTaskTimeMillis());
|
||||
|
||||
model.addAttribute("scatter", scatterData);
|
||||
|
||||
addResponseHeader(response);
|
||||
return "scatter_view";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/lastScatterView", method = RequestMethod.GET)
|
||||
public String getLastScatterView(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("period") long period, @RequestParam("limit") int limit) {
|
||||
long to = getQueryEndTime();
|
||||
long from = to - period;
|
||||
return getScatterView(model, response, applicationName, from, to, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -82,11 +55,11 @@ public class ScatterChartController extends BaseController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getScatterData", method = RequestMethod.GET)
|
||||
public String getScatterData(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("from") long from, @RequestParam("to") long to, @RequestParam("limit") int limit, @RequestParam(value="_callback", required=false) String jsonpCallback) {
|
||||
public String getScatterData(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("from") long from, @RequestParam("to") long to, @RequestParam("limit") int limit, @RequestParam(value = "_callback", required = false) String jsonpCallback) {
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start("selectScatterData");
|
||||
|
||||
List<Dot> scatterData = flow.selectScatterData(applicationName, from, to, limit);
|
||||
List<Dot> scatterData = scatter.selectScatterData(applicationName, from, to, limit);
|
||||
watch.stop();
|
||||
|
||||
logger.info("Fetch scatterData time : {}ms", watch.getLastTaskTimeMillis());
|
||||
@@ -94,7 +67,7 @@ public class ScatterChartController extends BaseController {
|
||||
model.addAttribute("scatter", scatterData);
|
||||
|
||||
addResponseHeader(response);
|
||||
|
||||
|
||||
if (jsonpCallback == null) {
|
||||
return "scatter_json";
|
||||
} else {
|
||||
@@ -114,7 +87,7 @@ public class ScatterChartController extends BaseController {
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/getLastScatterData", method = RequestMethod.GET)
|
||||
public String getLastScatterData(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("period") long period, @RequestParam("limit") int limit, @RequestParam(value="_callback", required=false) String jsonpCallback) {
|
||||
public String getLastScatterData(Model model, HttpServletResponse response, @RequestParam("application") String applicationName, @RequestParam("period") long period, @RequestParam("limit") int limit, @RequestParam(value = "_callback", required = false) String jsonpCallback) {
|
||||
long to = getQueryEndTime();
|
||||
long from = to - period;
|
||||
return getScatterData(model, response, applicationName, from, to, limit, jsonpCallback);
|
||||
@@ -139,7 +112,7 @@ public class ScatterChartController extends BaseController {
|
||||
|
||||
long to = getQueryEndTime();
|
||||
|
||||
List<Dot> scatterData = flow.selectScatterData(applicationName, from, to, limit);
|
||||
List<Dot> scatterData = scatter.selectScatterData(applicationName, from, to, limit);
|
||||
watch.stop();
|
||||
|
||||
logger.info("Fetch scatterData time : {}ms", watch.getLastTaskTimeMillis());
|
||||
@@ -167,13 +140,13 @@ public class ScatterChartController extends BaseController {
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/requestmetadata", method = RequestMethod.POST)
|
||||
public String requestmetadata(Model model, HttpServletRequest request, HttpServletResponse response) {
|
||||
@RequestMapping(value = "/transactionmetadata", method = RequestMethod.POST)
|
||||
public String transactionmetadata(Model model, HttpServletRequest request, HttpServletResponse response) {
|
||||
String TRACEID = "tr";
|
||||
String TIME = "ti";
|
||||
String RESPONSE_TIME = "re";
|
||||
|
||||
RequestMetadataQuery query = new RequestMetadataQuery();
|
||||
TransactionMetadataQuery query = new TransactionMetadataQuery();
|
||||
|
||||
int index = 0;
|
||||
while (true) {
|
||||
@@ -190,11 +163,11 @@ public class ScatterChartController extends BaseController {
|
||||
}
|
||||
|
||||
if (query.size() > 0) {
|
||||
List<SpanBo> metadata = spanService.selectRequestMetadata(query);
|
||||
List<SpanBo> metadata = scatter.selectTransactionMetadata(query);
|
||||
model.addAttribute("metadata", metadata);
|
||||
}
|
||||
|
||||
addResponseHeader(response);
|
||||
return "requestmetadata";
|
||||
return "transactionmetadata";
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.nhn.hippo.web.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.nhn.hippo.web.vo.ClientStatistics;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author netspider
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public interface ClientStatisticsDao {
|
||||
public List<Map<String, ClientStatistics>> selectClient(String applicationName, short serviceType, long from, long to);
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.nhn.hippo.web.dao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.nhn.hippo.web.vo.TerminalStatistics;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author netspider
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public interface TerminalStatisticsDao {
|
||||
/**
|
||||
*
|
||||
* @param applicationName
|
||||
* @param from
|
||||
* @param to
|
||||
* @return key=applicationname
|
||||
*/
|
||||
public List<Map<String, TerminalStatistics>> selectTerminal(String applicationName, long from, long to);
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import com.profiler.common.hbase.HBaseTables;
|
||||
import com.profiler.common.hbase.HbaseOperations2;
|
||||
import com.profiler.common.util.ApplicationMapStatisticsUtils;
|
||||
import com.profiler.common.util.TimeSlot;
|
||||
import com.profiler.common.util.TimeUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.profiler.common.hbase.HBaseTables;
|
||||
import com.profiler.common.hbase.HbaseOperations2;
|
||||
import com.profiler.common.util.ApplicationMapStatisticsUtils;
|
||||
import com.profiler.common.util.TimeSlot;
|
||||
import com.profiler.common.util.TimeUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.nhn.hippo.web.dao.hbase;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hadoop.hbase.client.Scan;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.hadoop.hbase.RowMapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.nhn.hippo.web.dao.ClientStatisticsDao;
|
||||
import com.nhn.hippo.web.vo.ClientStatistics;
|
||||
import com.profiler.common.hbase.HBaseTables;
|
||||
import com.profiler.common.hbase.HbaseOperations2;
|
||||
import com.profiler.common.util.ClientStatUtils;
|
||||
import com.profiler.common.util.TimeSlot;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author netspider
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
@Repository
|
||||
public class HbaseClientStatisticsDao implements ClientStatisticsDao {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private int scanCacheSize = 40;
|
||||
|
||||
@Autowired
|
||||
private HbaseOperations2 hbaseOperations2;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("clientStatisticsMapper")
|
||||
private RowMapper<Map<String, ClientStatistics>> clientStatisticsMapper;
|
||||
|
||||
@Override
|
||||
public List<Map<String, ClientStatistics>> selectClient(String applicationName, short serviceType, long from, long to) {
|
||||
Scan scan = createScan(applicationName, serviceType, from, to);
|
||||
return hbaseOperations2.find(HBaseTables.CLIENT_STATISTICS, scan, clientStatisticsMapper);
|
||||
}
|
||||
|
||||
private Scan createScan(String applicationName, short serviceType, long from, long to) {
|
||||
long startTime = TimeSlot.getStatisticsRowSlot(from);
|
||||
// hbase의 scanner를 사용하여 검색시 endTime은 검색 대상에 포함되지 않기 때문에, +1을 해줘야 된다.
|
||||
long endTime = TimeSlot.getStatisticsRowSlot(to) + 1;
|
||||
if (logger.isDebugEnabled()) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss,SSS");
|
||||
logger.debug("scan startTime:{} endTime:{}", simpleDateFormat.format(new Date(startTime)), simpleDateFormat.format(new Date(endTime)));
|
||||
}
|
||||
byte[] startKey = ClientStatUtils.makeRowKey(applicationName, serviceType, startTime);
|
||||
byte[] endKey = ClientStatUtils.makeRowKey(applicationName, serviceType, endTime);
|
||||
|
||||
Scan scan = new Scan();
|
||||
scan.setCaching(this.scanCacheSize);
|
||||
scan.setStartRow(startKey);
|
||||
scan.setStopRow(endKey);
|
||||
scan.addFamily(HBaseTables.CLIENT_STATISTICS_CF_COUNTER);
|
||||
scan.setId("clientStatisticsScan");
|
||||
|
||||
return scan;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.nhn.hippo.web.dao.hbase;
|
||||
|
||||
import java.sql.Date;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hadoop.hbase.client.Scan;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.data.hadoop.hbase.RowMapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import com.nhn.hippo.web.dao.TerminalStatisticsDao;
|
||||
import com.nhn.hippo.web.vo.TerminalStatistics;
|
||||
import com.profiler.common.hbase.HBaseTables;
|
||||
import com.profiler.common.hbase.HbaseOperations2;
|
||||
import com.profiler.common.util.TerminalSpanUtils;
|
||||
import com.profiler.common.util.TimeSlot;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author netspider
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
@Repository
|
||||
public class HbaseTerminalStatisticsDao implements TerminalStatisticsDao {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private int scanCacheSize = 40;
|
||||
|
||||
@Autowired
|
||||
private HbaseOperations2 hbaseOperations2;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("terminalStatisticsMapper")
|
||||
private RowMapper<Map<String, TerminalStatistics>> terminalStatisticsMapper;
|
||||
|
||||
@Override
|
||||
public List<Map<String, TerminalStatistics>> selectTerminal(String applicationName, long from, long to) {
|
||||
Scan scan = createScan(applicationName, from, to);
|
||||
return hbaseOperations2.find(HBaseTables.TERMINAL_STATISTICS, scan, terminalStatisticsMapper);
|
||||
}
|
||||
|
||||
private Scan createScan(String applicationName, long from, long to) {
|
||||
long startTime = TimeSlot.getStatisticsRowSlot(from);
|
||||
// hbase의 scanner를 사용하여 검색시 endTime은 검색 대상에 포함되지 않기 때문에, +1을 해줘야 된다.
|
||||
long endTime = TimeSlot.getStatisticsRowSlot(to) + 1;
|
||||
if (logger.isDebugEnabled()) {
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss,SSS");
|
||||
logger.debug("scan startTime:{} endTime:{}", simpleDateFormat.format(new Date(startTime)), simpleDateFormat.format(new Date(endTime)));
|
||||
}
|
||||
byte[] startKey = TerminalSpanUtils.makeRowKey(applicationName, startTime);
|
||||
byte[] endKey = TerminalSpanUtils.makeRowKey(applicationName, endTime);
|
||||
|
||||
Scan scan = new Scan();
|
||||
scan.setCaching(this.scanCacheSize);
|
||||
scan.setStartRow(startKey);
|
||||
scan.setStopRow(endKey);
|
||||
scan.addFamily(HBaseTables.TERMINAL_STATISTICS_CF_COUNTER);
|
||||
scan.setId("terminalStatisticsScan");
|
||||
|
||||
return scan;
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.nhn.hippo.web.mapper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.hadoop.hbase.KeyValue;
|
||||
import org.apache.hadoop.hbase.client.Result;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.springframework.data.hadoop.hbase.RowMapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.nhn.hippo.web.vo.ClientStatistics;
|
||||
import com.profiler.common.hbase.HBaseTables;
|
||||
import com.profiler.common.util.ClientStatUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author netspider
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class ClientStatisticsMapper implements RowMapper<Map<String, ClientStatistics>> {
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* rowkey = applicationName + serviceType + timeslot
|
||||
* cf = Count
|
||||
* cq = Slot
|
||||
* </pre>
|
||||
*/
|
||||
@Override
|
||||
public Map<String, ClientStatistics> mapRow(Result result, int rowNum) throws Exception {
|
||||
KeyValue[] keyList = result.raw();
|
||||
|
||||
// key is destApplicationName.
|
||||
Map<String, ClientStatistics> stat = new HashMap<String, ClientStatistics>();
|
||||
|
||||
for (KeyValue kv : keyList) {
|
||||
if (kv.getFamilyLength() != HBaseTables.CLIENT_STATISTICS_CF_COUNTER.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] qualifier = kv.getQualifier();
|
||||
|
||||
String destApplicationName = ClientStatUtils.getApplicationNameFromRowKey(kv.getRow());
|
||||
short destServiceType = ClientStatUtils.getApplicationServiceTypeFromRowKey(kv.getRow());
|
||||
long requestCount = Bytes.toLong(kv.getValue());
|
||||
short histogramSlot = ClientStatUtils.getHistogramSlotFromColumnName(qualifier);
|
||||
boolean isError = histogramSlot == (short) -1;
|
||||
|
||||
if (stat.containsKey(destApplicationName)) {
|
||||
ClientStatistics statistics = stat.get(destApplicationName);
|
||||
if (isError) {
|
||||
statistics.getHistogram().incrErrorCount(requestCount);
|
||||
} else {
|
||||
statistics.getHistogram().addSample(histogramSlot, requestCount);
|
||||
}
|
||||
} else {
|
||||
ClientStatistics statistics = new ClientStatistics(destApplicationName, destServiceType);
|
||||
if (isError) {
|
||||
statistics.getHistogram().incrErrorCount(requestCount);
|
||||
} else {
|
||||
statistics.getHistogram().addSample(histogramSlot, requestCount);
|
||||
}
|
||||
stat.put(destApplicationName, statistics);
|
||||
}
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package com.nhn.hippo.web.mapper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.hadoop.hbase.KeyValue;
|
||||
import org.apache.hadoop.hbase.client.Result;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.springframework.data.hadoop.hbase.RowMapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.nhn.hippo.web.vo.TerminalStatistics;
|
||||
import com.profiler.common.hbase.HBaseTables;
|
||||
import com.profiler.common.util.TerminalSpanUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class TerminalStatisticsMapper implements RowMapper<Map<String, TerminalStatistics>> {
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* rowkey = applicationName + timeslot
|
||||
* cf = Cnt, ErrCnt
|
||||
* cn = ServiceType + Slot + ApplicationName
|
||||
*
|
||||
* output format
|
||||
* {
|
||||
* hippo={
|
||||
* From=TOMCAT11, To=hippo, ToSvcType=2101, Histogram={ "1000" : 3, "3000" : 0, "5000" : 0 }
|
||||
* },
|
||||
* dev={
|
||||
* From=TOMCAT11, To=dev, ToSvcType=8100, Histogram={ "100" : 1, "300" : 0, "500" : 0 }
|
||||
* },
|
||||
* MEMCACHED={
|
||||
* From=TOMCAT11, To=MEMCACHED, ToSvcType=8050, Histogram={ "100" : 1, "300" : 0, "500" : 0 }
|
||||
* },
|
||||
* section.cafe.naver.com={
|
||||
* From=TOMCAT11, To=section.cafe.naver.com, ToSvcType=9050, Histogram={ "1000" : 2, "3000" : 0, "5000" : 0 }
|
||||
* },
|
||||
* www.naver.com={
|
||||
* From=TOMCAT11, To=www.naver.com, ToSvcType=9050, Histogram={ "1000" : 2, "3000" : 0, "5000" : 0 }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Override
|
||||
public Map<String, TerminalStatistics> mapRow(Result result, int rowNum) throws Exception {
|
||||
KeyValue[] keyList = result.raw();
|
||||
|
||||
// key is destApplicationName.
|
||||
Map<String, TerminalStatistics> stat = new HashMap<String, TerminalStatistics>();
|
||||
|
||||
// key is destApplicationName
|
||||
Map<String, Set<String>> destAppHostMap = new HashMap<String, Set<String>>();
|
||||
|
||||
for (KeyValue kv : keyList) {
|
||||
if (kv.getFamilyLength() != HBaseTables.TERMINAL_STATISTICS_CF_COUNTER.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] qualifier = kv.getQualifier();
|
||||
|
||||
String srcApplicationName = TerminalSpanUtils.getApplicationNameFromRowKey(kv.getRow());
|
||||
String destApplicationName = TerminalSpanUtils.getDestApplicationNameFromColumnName(qualifier);
|
||||
long requestCount = Bytes.toLong(kv.getValue());
|
||||
short destServiceType = TerminalSpanUtils.getDestServiceTypeFromColumnName(qualifier);
|
||||
short histogramSlot = TerminalSpanUtils.getHistogramSlotFromColumnName(qualifier);
|
||||
String host = TerminalSpanUtils.getHost(qualifier);
|
||||
boolean isError = histogramSlot == (short) -1;
|
||||
|
||||
// hostname은 일단 따로 보관.
|
||||
if (host != null) {
|
||||
if (destAppHostMap.containsKey(destApplicationName)) {
|
||||
destAppHostMap.get(destApplicationName).add(host);
|
||||
} else {
|
||||
Set<String> set = new HashSet<String>();
|
||||
set.add(host);
|
||||
destAppHostMap.put(destApplicationName, set);
|
||||
}
|
||||
}
|
||||
|
||||
if (stat.containsKey(destApplicationName)) {
|
||||
TerminalStatistics statistics = stat.get(destApplicationName);
|
||||
if (isError) {
|
||||
statistics.getHistogram().incrErrorCount(requestCount);
|
||||
} else {
|
||||
statistics.getHistogram().addSample(histogramSlot, requestCount);
|
||||
}
|
||||
} else {
|
||||
TerminalStatistics statistics = new TerminalStatistics(srcApplicationName, destApplicationName, destServiceType);
|
||||
if (isError) {
|
||||
statistics.getHistogram().incrErrorCount(requestCount);
|
||||
} else {
|
||||
statistics.getHistogram().addSample(histogramSlot, requestCount);
|
||||
}
|
||||
stat.put(destApplicationName, statistics);
|
||||
}
|
||||
}
|
||||
|
||||
// statistics에 dest host정보 삽입.
|
||||
for (Entry<String, TerminalStatistics> entry : stat.entrySet()) {
|
||||
entry.getValue().addHosts(destAppHostMap.get(entry.getKey()));
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
}
|
||||
@@ -7,73 +7,17 @@ import com.nhn.hippo.web.calltree.server.ServerCallTree;
|
||||
import com.nhn.hippo.web.vo.Application;
|
||||
import com.nhn.hippo.web.vo.BusinessTransactions;
|
||||
import com.nhn.hippo.web.vo.TraceId;
|
||||
import com.nhn.hippo.web.vo.scatter.Dot;
|
||||
|
||||
/**
|
||||
* @author netspider
|
||||
*/
|
||||
public interface FlowChartService {
|
||||
|
||||
/**
|
||||
* select agentIds from application name
|
||||
*
|
||||
* @param hosts
|
||||
* @return
|
||||
*/
|
||||
public String[] selectAgentIdsFromApplicationName(String applicationName);
|
||||
|
||||
/**
|
||||
* select traceIds from TraceIndex table
|
||||
*
|
||||
* @param agentIds
|
||||
* @param from
|
||||
* @param to
|
||||
* @return
|
||||
*/
|
||||
public Set<TraceId> selectTraceIdsFromTraceIndex(String[] agentIds, long from, long to);
|
||||
|
||||
/**
|
||||
* select traceIds from ApplicationTraceIndex table
|
||||
*
|
||||
* @param agentIds
|
||||
* @param from
|
||||
* @param to
|
||||
* @return
|
||||
*/
|
||||
public Set<TraceId> selectTraceIdsFromApplicationTraceIndex(String applicationName, long from, long to);
|
||||
|
||||
/**
|
||||
* select call tree
|
||||
*
|
||||
* @param traceIds
|
||||
* @return
|
||||
*/
|
||||
public ServerCallTree selectServerCallTree(Set<TraceId> traceIds);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param traceIds
|
||||
* @param applicationName
|
||||
* @param from
|
||||
* @param to
|
||||
* @return
|
||||
*/
|
||||
public ServerCallTree selectServerCallTree(Set<TraceId> traceIds, String applicationName, long from, long to);
|
||||
|
||||
/**
|
||||
* select all application names
|
||||
*
|
||||
* @return all of application names
|
||||
*/
|
||||
public List<Application> selectAllApplicationNames();
|
||||
|
||||
public String[] selectAgentIds(String[] hosts);
|
||||
|
||||
public ServerCallTree selectServerCallTree(TraceId traceId);
|
||||
|
||||
public List<Dot> selectScatterData(String applicationName, long from, long to);
|
||||
|
||||
public List<Dot> selectScatterData(String applicationName, long from, long to, int limit);
|
||||
|
||||
|
||||
public BusinessTransactions selectBusinessTransactions(Set<TraceId> traceIds, String applicationName, long from, long to);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.nhn.hippo.web.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -15,23 +12,14 @@ 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.ServerCallTree;
|
||||
import com.nhn.hippo.web.dao.AgentInfoDao;
|
||||
import com.nhn.hippo.web.dao.ApplicationIndexDao;
|
||||
import com.nhn.hippo.web.dao.ApplicationTraceIndexDao;
|
||||
import com.nhn.hippo.web.dao.ClientStatisticsDao;
|
||||
import com.nhn.hippo.web.dao.TerminalStatisticsDao;
|
||||
import com.nhn.hippo.web.dao.TraceDao;
|
||||
import com.nhn.hippo.web.dao.TraceIndexDao;
|
||||
import com.nhn.hippo.web.vo.Application;
|
||||
import com.nhn.hippo.web.vo.BusinessTransactions;
|
||||
import com.nhn.hippo.web.vo.ClientStatistics;
|
||||
import com.nhn.hippo.web.vo.TerminalStatistics;
|
||||
import com.nhn.hippo.web.vo.TraceId;
|
||||
import com.nhn.hippo.web.vo.scatter.Dot;
|
||||
import com.profiler.common.ServiceType;
|
||||
import com.profiler.common.bo.AgentInfoBo;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import com.profiler.common.bo.SpanEventBo;
|
||||
|
||||
@@ -46,86 +34,17 @@ public class FlowChartServiceImpl implements FlowChartService {
|
||||
@Autowired
|
||||
private TraceDao traceDao;
|
||||
|
||||
@Autowired
|
||||
private TraceIndexDao traceIndexDao;
|
||||
|
||||
@Autowired
|
||||
private ApplicationIndexDao applicationIndexDao;
|
||||
|
||||
@Autowired
|
||||
private ApplicationTraceIndexDao applicationTraceIndexDao;
|
||||
|
||||
@Autowired
|
||||
private TerminalStatisticsDao terminalStatisticsDao;
|
||||
|
||||
@Autowired
|
||||
private ClientStatisticsDao clientStatisticsDao;
|
||||
|
||||
@Autowired
|
||||
private AgentInfoDao agentInfoDao;
|
||||
|
||||
@Override
|
||||
public List<Application> selectAllApplicationNames() {
|
||||
return applicationIndexDao.selectAllApplicationNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] selectAgentIdsFromApplicationName(String applicationName) {
|
||||
return applicationIndexDao.selectAgentIds(applicationName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceId> selectTraceIdsFromTraceIndex(String[] agentIds, long from, long to) {
|
||||
if (agentIds == null) {
|
||||
throw new NullPointerException("agentIds");
|
||||
}
|
||||
|
||||
if (agentIds.length == 1) {
|
||||
// single scan
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("scan {}, {}, {}", new Object[] { agentIds[0], from, to });
|
||||
}
|
||||
List<List<TraceId>> bytes = this.traceIndexDao.scanTraceIndex(agentIds[0], from, to);
|
||||
Set<TraceId> result = new HashSet<TraceId>();
|
||||
for (List<TraceId> list : bytes) {
|
||||
for (TraceId traceId : list) {
|
||||
result.add(traceId);
|
||||
logger.trace("traceid:{}", traceId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
// multi scan 가능한 동일 open htable 에서 액세스함.
|
||||
List<List<List<TraceId>>> multiScan = this.traceIndexDao.multiScanTraceIndex(agentIds, from, to);
|
||||
Set<TraceId> result = new HashSet<TraceId>();
|
||||
for (List<List<TraceId>> list : multiScan) {
|
||||
for (List<TraceId> scan : list) {
|
||||
for (TraceId traceId : scan) {
|
||||
result.add(traceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public ServerCallTree selectServerCallTree(Set<TraceId> traceIds) {
|
||||
final ServerCallTree tree = new ServerCallTree(new ApplicationIdNodeSelector());
|
||||
|
||||
List<List<SpanBo>> traces = this.traceDao.selectSpans(traceIds);
|
||||
|
||||
for (List<SpanBo> transaction : traces) {
|
||||
// List<SpanBo> processed = refine(transaction);
|
||||
// markRecursiveCall(transaction);
|
||||
for (SpanBo eachTransaction : transaction) {
|
||||
tree.addSpan(eachTransaction);
|
||||
}
|
||||
}
|
||||
return tree.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* DetailView에서 사용함. 하나의 Span을 선택했을때 Draw되는 데이터를 생성하는 함수이다 makes call tree
|
||||
* of transaction detail view
|
||||
@@ -145,7 +64,7 @@ public class FlowChartServiceImpl implements FlowChartService {
|
||||
tree.addSpanEventList(spanEventBoList);
|
||||
|
||||
tree.build();
|
||||
|
||||
|
||||
watch.stop();
|
||||
logger.info("Fetch single transaction serverCallTree elapsed. {}ms", watch.getLastTaskTimeMillis());
|
||||
|
||||
@@ -216,150 +135,6 @@ public class FlowChartServiceImpl implements FlowChartService {
|
||||
return endPointSet;
|
||||
}
|
||||
|
||||
private Set<String> selectApplicationHosts(String applicationId) {
|
||||
String[] agentIds = applicationIndexDao.selectAgentIds(applicationId);
|
||||
|
||||
Set<String> hostnames = new HashSet<String>();
|
||||
|
||||
for (String agentId : agentIds) {
|
||||
// TODO 조회 시간대에 따라서 agent info row timestamp를 변경하여 조회해야하는지는 모르겠음.
|
||||
AgentInfoBo info = agentInfoDao.findAgentInfoBeforeStartTime(agentId, System.currentTimeMillis());
|
||||
hostnames.add(info.getHostname());
|
||||
}
|
||||
|
||||
return hostnames;
|
||||
}
|
||||
|
||||
/**
|
||||
* 메인화면에서 사용. 시간별로 TimeSlot을 조회하여 서버 맵을 그릴 때 사용한다. makes call tree of main
|
||||
* view
|
||||
*/
|
||||
@Override
|
||||
public ServerCallTree selectServerCallTree(Set<TraceId> traceIds, String applicationName, long from, long to) {
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start();
|
||||
|
||||
final Map<String, ServiceType> terminalQueryParams = new HashMap<String, ServiceType>();
|
||||
final Map<String, ServiceType> clientQueryParams = new HashMap<String, ServiceType>();
|
||||
final Set<String> hostnameQueryParams = new HashSet<String>();
|
||||
final ServerCallTree tree = new ServerCallTree(new ApplicationIdNodeSelector());
|
||||
|
||||
// fetch non-terminal spans
|
||||
List<List<SpanBo>> traces = this.traceDao.selectSpans(traceIds);
|
||||
|
||||
int totalNonTerminalSpansCount = 0;
|
||||
|
||||
Set<String> nonTerminalEndPoints = new HashSet<String>();
|
||||
|
||||
// processing spans
|
||||
for (List<SpanBo> transaction : traces) {
|
||||
totalNonTerminalSpansCount += transaction.size();
|
||||
|
||||
// List<SpanBo> processed = refine(transaction);
|
||||
// markRecursiveCall(transaction);
|
||||
for (SpanBo eachTransaction : transaction) {
|
||||
tree.addSpan(eachTransaction);
|
||||
|
||||
// make hostname query params
|
||||
hostnameQueryParams.add(eachTransaction.getApplicationId());
|
||||
|
||||
// make query param
|
||||
terminalQueryParams.put(eachTransaction.getApplicationId(), eachTransaction.getServiceType());
|
||||
|
||||
// make client query param
|
||||
if (eachTransaction.isRoot()) {
|
||||
// TODO 여기에서 service type을 CLIENT로 지정해버려서 client유형별로 조회 불가능. 나중에 고쳐야함.
|
||||
clientQueryParams.put(eachTransaction.getApplicationId(), ServiceType.CLIENT);
|
||||
}
|
||||
|
||||
nonTerminalEndPoints.add(eachTransaction.getEndPoint());
|
||||
}
|
||||
}
|
||||
|
||||
// fetch terminal info
|
||||
for (Entry<String, ServiceType> param : terminalQueryParams.entrySet()) {
|
||||
ServiceType svcType = param.getValue();
|
||||
if (!svcType.isRpcClient() && !svcType.isUnknown() && !svcType.isTerminal()) {
|
||||
long start = System.currentTimeMillis();
|
||||
List<Map<String, TerminalStatistics>> terminals = terminalStatisticsDao.selectTerminal(param.getKey(), from, to);
|
||||
logger.info(" Fetch terminals of {} : {}ms", param.getKey(), System.currentTimeMillis() - start);
|
||||
|
||||
for (Map<String, TerminalStatistics> terminal : terminals) {
|
||||
for (Entry<String, TerminalStatistics> entry : terminal.entrySet()) {
|
||||
// TODO 임시방편
|
||||
TerminalStatistics terminalStatistics = entry.getValue();
|
||||
|
||||
// 이 요청의 destination이 수집된 trace정보에 없으면 unknown cloud로 처리한다.
|
||||
if (!nonTerminalEndPoints.contains(terminalStatistics.getTo())) {
|
||||
|
||||
if (ServiceType.findServiceType(terminalStatistics.getToServiceType()).isRpcClient()) {
|
||||
terminalStatistics.setToServiceType(ServiceType.UNKNOWN_CLOUD.getCode());
|
||||
}
|
||||
|
||||
tree.addTerminalStatistics(terminalStatistics);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("client query params=" + clientQueryParams);
|
||||
|
||||
// fetch client info
|
||||
for (Entry<String, ServiceType> param : clientQueryParams.entrySet()) {
|
||||
List<Map<String, ClientStatistics>> clients = clientStatisticsDao.selectClient(param.getKey(), param.getValue().getCode(), from, to);
|
||||
|
||||
for (Map<String, ClientStatistics> client : clients) {
|
||||
for (Entry<String, ClientStatistics> clientEntry : client.entrySet()) {
|
||||
logger.debug("fetched client=" + clientEntry);
|
||||
tree.addClientStatistics(clientEntry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("hostname query params=" + hostnameQueryParams);
|
||||
|
||||
// fetch hostnames
|
||||
for (String applicationId : hostnameQueryParams) {
|
||||
tree.addApplicationHosts(applicationId, selectApplicationHosts(applicationId));
|
||||
}
|
||||
|
||||
tree.build();
|
||||
|
||||
watch.stop();
|
||||
logger.info("Fetch serverCallTree elapsed. {}ms", watch.getLastTaskTimeMillis());
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private SpanBo findChildSpan(final List<SpanBo> list, final SpanBo parent) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
SpanBo child = list.get(i);
|
||||
|
||||
if (child.getParentSpanId() == parent.getSpanId()) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* server map이 recursive call을 표현할 수 있게 되어 필요 없음.
|
||||
*
|
||||
* @param list
|
||||
*/
|
||||
@Deprecated
|
||||
private void markRecursiveCall(final List<SpanBo> list) {
|
||||
/*
|
||||
* for (int i = 0; i < list.size(); i++) { SpanBo a = list.get(i); for
|
||||
* (int j = 0; j < list.size(); j++) { if (i == j) continue; SpanBo b =
|
||||
* list.get(j); if (a.getServiceName().equals(b.getServiceName()) &&
|
||||
* a.getSpanId() == b.getParentSpanId()) {
|
||||
* a.increaseRecursiveCallCount(); } } }
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<TraceId> selectTraceIdsFromApplicationTraceIndex(String applicationName, long from, long to) {
|
||||
if (applicationName == null) {
|
||||
@@ -381,55 +156,13 @@ public class FlowChartServiceImpl implements FlowChartService {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public String[] selectAgentIds(String[] hosts) {
|
||||
// List<HbaseColumn> column = new ArrayList<HBaseQuery.HbaseColumn>();
|
||||
// column.add(new HbaseColumn("Agents", "AgentID"));
|
||||
//
|
||||
// HBaseQuery query = new HBaseQuery(HBaseTables.APPLICATION_INDEX,
|
||||
// null, null, column);
|
||||
// Iterator<Map<String, byte[]>> iterator = client.getHBaseData(query);
|
||||
//
|
||||
// if (logger.isDebugEnabled()) {
|
||||
// while (iterator.hasNext()) {
|
||||
// logger.debug("selectedAgentId={}", iterator.next());
|
||||
// }
|
||||
// logger.debug("!!!==============WARNING==============!!!");
|
||||
// logger.debug("!!! selectAgentIds IS NOT IMPLEMENTED !!!");
|
||||
// logger.debug("!!!===================================!!!");
|
||||
// }
|
||||
|
||||
return hosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Dot> selectScatterData(String applicationName, long from, long to) {
|
||||
List<List<Dot>> scanTrace = applicationTraceIndexDao.scanTraceScatter(applicationName, from, to);
|
||||
|
||||
List<Dot> list = new ArrayList<Dot>();
|
||||
|
||||
for (List<Dot> l : scanTrace) {
|
||||
for (Dot dot : l) {
|
||||
list.add(dot);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Dot> selectScatterData(String applicationName, long from, long to, int limit) {
|
||||
return applicationTraceIndexDao.scanTraceScatter2(applicationName, from, to, limit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusinessTransactions selectBusinessTransactions(Set<TraceId> traceIds, String applicationName, long from, long to) {
|
||||
List<List<SpanBo>> traceList = this.traceDao.selectSpans(traceIds);
|
||||
|
||||
BusinessTransactions businessTransactions = new BusinessTransactions();
|
||||
for (List<SpanBo> trace : traceList) {
|
||||
for (SpanBo spanBo : trace ) {
|
||||
for (SpanBo spanBo : trace) {
|
||||
// 해당 application으로 인입된 요청만 보여준다.
|
||||
if (applicationName.equals(spanBo.getApplicationId())) {
|
||||
businessTransactions.add(spanBo);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.nhn.hippo.web.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.nhn.hippo.web.calltree.span.SpanAlign;
|
||||
import com.nhn.hippo.web.vo.callstacks.RecordSet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
package com.nhn.hippo.web.service;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.nhn.hippo.web.calltree.span.SpanAlign;
|
||||
import com.nhn.hippo.web.vo.callstacks.Record;
|
||||
import com.nhn.hippo.web.vo.callstacks.RecordSet;
|
||||
@@ -11,11 +17,6 @@ import com.profiler.common.bo.SpanEventBo;
|
||||
import com.profiler.common.util.AnnotationUtils;
|
||||
import com.profiler.common.util.ApiDescription;
|
||||
import com.profiler.common.util.ApiDescriptionParser;
|
||||
import org.apache.commons.lang.ObjectUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.nhn.hippo.web.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.nhn.hippo.web.vo.TransactionMetadataQuery;
|
||||
import com.nhn.hippo.web.vo.scatter.Dot;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
|
||||
public interface ScatterChartService {
|
||||
public List<Dot> selectScatterData(String applicationName, long from, long to, int limit);
|
||||
|
||||
public List<SpanBo> selectTransactionMetadata(TransactionMetadataQuery query);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.nhn.hippo.web.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.nhn.hippo.web.dao.ApplicationTraceIndexDao;
|
||||
import com.nhn.hippo.web.dao.TraceDao;
|
||||
import com.nhn.hippo.web.vo.TransactionMetadataQuery;
|
||||
import com.nhn.hippo.web.vo.scatter.Dot;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
|
||||
/**
|
||||
* @author netspider
|
||||
*/
|
||||
@Service
|
||||
public class ScatterChartServiceImpl implements ScatterChartService {
|
||||
|
||||
@Autowired
|
||||
private ApplicationTraceIndexDao applicationTraceIndexDao;
|
||||
|
||||
@Autowired
|
||||
private TraceDao traceDao;
|
||||
|
||||
@Override
|
||||
public List<Dot> selectScatterData(String applicationName, long from, long to, int limit) {
|
||||
return applicationTraceIndexDao.scanTraceScatter2(applicationName, from, to, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* scatter chart에서 선택한 점에 대한 정보를 조회 하는 메소드.
|
||||
*/
|
||||
@Override
|
||||
public List<SpanBo> selectTransactionMetadata(TransactionMetadataQuery query) {
|
||||
List<List<SpanBo>> selectedSpans = traceDao.selectSpans(query.getTraceIds());
|
||||
|
||||
List<SpanBo> result = new ArrayList<SpanBo>(query.size());
|
||||
|
||||
// 조회된 녀석들 중에서 UUID, starttime, responseTime이 같은것들만 골라냄.
|
||||
for (List<SpanBo> spans : selectedSpans) {
|
||||
for (SpanBo span : spans) {
|
||||
// check UUID and time
|
||||
if (query.isExists(span.getMostTraceId(), span.getLeastTraceId(), span.getCollectorAcceptTime(), span.getElapsed())) {
|
||||
result.add(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 일단 임시로...
|
||||
Collections.sort(result, new Comparator<SpanBo>() {
|
||||
@Override
|
||||
public int compare(SpanBo o1, SpanBo o2) {
|
||||
if (o1.getException() != 0 && o2.getException() != 0) {
|
||||
return o2.getElapsed() - o1.getElapsed();
|
||||
} else if (o1.getException() != 0) {
|
||||
return -1;
|
||||
} else if (o2.getException() != 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return o2.getElapsed() - o1.getElapsed();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,11 @@ package com.nhn.hippo.web.service;
|
||||
import java.util.List;
|
||||
|
||||
import com.nhn.hippo.web.calltree.span.SpanAlign;
|
||||
import com.nhn.hippo.web.vo.RequestMetadataQuery;
|
||||
import com.nhn.hippo.web.vo.TraceId;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface SpanService {
|
||||
List<SpanAlign> selectSpan(TraceId traceId);
|
||||
|
||||
List<SpanBo> selectRequestMetadata(RequestMetadataQuery query);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
package com.nhn.hippo.web.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import com.nhn.hippo.web.vo.TraceId;
|
||||
import com.profiler.common.AnnotationKey;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -18,7 +14,8 @@ import com.nhn.hippo.web.dao.AgentInfoDao;
|
||||
import com.nhn.hippo.web.dao.ApiMetaDataDao;
|
||||
import com.nhn.hippo.web.dao.SqlMetaDataDao;
|
||||
import com.nhn.hippo.web.dao.TraceDao;
|
||||
import com.nhn.hippo.web.vo.RequestMetadataQuery;
|
||||
import com.nhn.hippo.web.vo.TraceId;
|
||||
import com.profiler.common.AnnotationKey;
|
||||
import com.profiler.common.bo.AgentInfoBo;
|
||||
import com.profiler.common.bo.AnnotationBo;
|
||||
import com.profiler.common.bo.ApiMetaDataBo;
|
||||
@@ -36,379 +33,335 @@ import com.profiler.common.util.SqlParser;
|
||||
@Service
|
||||
public class SpanServiceImpl implements SpanService {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private TraceDao traceDao;
|
||||
@Autowired
|
||||
private TraceDao traceDao;
|
||||
|
||||
@Autowired
|
||||
private SqlMetaDataDao sqlMetaDataDao;
|
||||
@Autowired
|
||||
private SqlMetaDataDao sqlMetaDataDao;
|
||||
|
||||
@Autowired
|
||||
private ApiMetaDataDao apiMetaDataDao;
|
||||
@Autowired
|
||||
private ApiMetaDataDao apiMetaDataDao;
|
||||
|
||||
@Autowired
|
||||
private AgentInfoDao agentInfoDao;
|
||||
@Autowired
|
||||
private AgentInfoDao agentInfoDao;
|
||||
|
||||
private SqlParser sqlParser = new SqlParser();
|
||||
private OutputParameterParser outputParameterParser = new OutputParameterParser();
|
||||
private SqlParser sqlParser = new SqlParser();
|
||||
private OutputParameterParser outputParameterParser = new OutputParameterParser();
|
||||
|
||||
@Override
|
||||
public List<SpanAlign> selectSpan(TraceId traceId) {
|
||||
@Override
|
||||
public List<SpanAlign> selectSpan(TraceId traceId) {
|
||||
|
||||
List<SpanBo> spans = traceDao.selectSpanAndAnnotation(traceId);
|
||||
if (spans == null || spans.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<SpanBo> spans = traceDao.selectSpanAndAnnotation(traceId);
|
||||
if (spans == null || spans.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<SpanAlign> order = order(spans);
|
||||
transitionApiId(order);
|
||||
transitionDynamicApiId(order);
|
||||
transitionSqlId(order);
|
||||
// TODO root span not found시 row data라도 보여줘야 됨.
|
||||
List<SpanAlign> order = order(spans);
|
||||
transitionApiId(order);
|
||||
transitionDynamicApiId(order);
|
||||
transitionSqlId(order);
|
||||
// TODO root span not found시 row data라도 보여줘야 됨.
|
||||
|
||||
return order;
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
private void transitionAnnotation(List<SpanAlign> spans, AnnotationReplacementCallback annotationReplacementCallback) {
|
||||
for (SpanAlign spanAlign : spans) {
|
||||
List<AnnotationBo> annotationBoList;
|
||||
if (spanAlign.isSpan()) {
|
||||
annotationBoList = spanAlign.getSpanBo().getAnnotationBoList();
|
||||
annotationReplacementCallback.replacement(spanAlign, annotationBoList);
|
||||
} else {
|
||||
annotationBoList = spanAlign.getSpanEventBo().getAnnotationBoList();
|
||||
annotationReplacementCallback.replacement(spanAlign, annotationBoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void transitionAnnotation(List<SpanAlign> spans, AnnotationReplacementCallback annotationReplacementCallback) {
|
||||
for (SpanAlign spanAlign : spans) {
|
||||
List<AnnotationBo> annotationBoList;
|
||||
if (spanAlign.isSpan()) {
|
||||
annotationBoList = spanAlign.getSpanBo().getAnnotationBoList();
|
||||
annotationReplacementCallback.replacement(spanAlign, annotationBoList);
|
||||
} else {
|
||||
annotationBoList = spanAlign.getSpanEventBo().getAnnotationBoList();
|
||||
annotationReplacementCallback.replacement(spanAlign, annotationBoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void transitionSqlId(final List<SpanAlign> spans) {
|
||||
this.transitionAnnotation(spans, new AnnotationReplacementCallback() {
|
||||
@Override
|
||||
public void replacement(SpanAlign spanAlign, List<AnnotationBo> annotationBoList) {
|
||||
AnnotationBo sqlIdAnnotation = findAnnotation(annotationBoList, AnnotationKey.SQL_ID.getCode());
|
||||
if (sqlIdAnnotation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AgentInfoBo agentInfoBo = null;
|
||||
try {
|
||||
agentInfoBo = findAgentInfoBoBeforeStartTime(spanAlign);
|
||||
logger.info("{} Agent StartTime found:{}", agentInfoBo.getAgentId(), agentInfoBo);
|
||||
} catch (AgentIdNotFoundException ex) {
|
||||
AnnotationBo agentInfoNotFound = new AnnotationBo();
|
||||
agentInfoNotFound.setKey(AnnotationKey.SQL.getCode());
|
||||
agentInfoNotFound.setValue("SQL-ID not found. Cause:agentInfo not found. agentId:" + ex.getAgentId() + " startTime:" + ex.getStartTime());
|
||||
annotationBoList.add(agentInfoNotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO 일단 시간까지 조회는 하지 말고 하자.
|
||||
// 미리 sqlMetaDataList를 indentifier로 필터치는 로직이 더 좋을것으로 생각됨.
|
||||
int hashCode = (Integer) sqlIdAnnotation.getValue();
|
||||
List<SqlMetaDataBo> sqlMetaDataList = sqlMetaDataDao.getSqlMetaData(agentInfoBo.getAgentId(), agentInfoBo.getIdentifier(), hashCode, agentInfoBo.getTimestamp());
|
||||
int size = sqlMetaDataList.size();
|
||||
if (size == 0) {
|
||||
AnnotationBo api = new AnnotationBo();
|
||||
api.setKey(AnnotationKey.SQL.getCode());
|
||||
api.setValue("SQL-ID not found hashCode:" + hashCode);
|
||||
annotationBoList.add(api);
|
||||
} else if (size == 1) {
|
||||
AnnotationBo sqlParamAnnotationBo = findAnnotation(annotationBoList, AnnotationKey.SQL_PARAM.getCode());
|
||||
final SqlMetaDataBo sqlMetaDataBo = sqlMetaDataList.get(0);
|
||||
if (sqlParamAnnotationBo == null) {
|
||||
AnnotationBo sqlMeta = new AnnotationBo();
|
||||
sqlMeta.setKey(AnnotationKey.SQL_METADATA.getCode());
|
||||
sqlMeta.setValue(sqlMetaDataBo.getSql());
|
||||
annotationBoList.add(sqlMeta);
|
||||
|
||||
AnnotationBo checkFail = checkIdentifier (spanAlign, sqlMetaDataBo);
|
||||
if (checkFail != null) {
|
||||
// 실패
|
||||
annotationBoList.add(checkFail);
|
||||
return;
|
||||
}
|
||||
|
||||
AnnotationBo sql = new AnnotationBo();
|
||||
sql.setKey(AnnotationKey.SQL.getCode());
|
||||
sql.setValue(sqlMetaDataBo.getSql());
|
||||
annotationBoList.add(sql);
|
||||
} else {
|
||||
logger.debug("sqlMetaDataBo:{}", sqlMetaDataBo);
|
||||
String outputParams = (String) sqlParamAnnotationBo.getValue();
|
||||
List<String> parsedOutputParams = outputParameterParser.parseOutputParameter(outputParams);
|
||||
logger.debug("outputPrams:{}, parsedOutputPrams:{}", outputParams, parsedOutputParams);
|
||||
String originalSql = sqlParser.combineOutputParams(sqlMetaDataBo.getSql(), parsedOutputParams);
|
||||
logger.debug("outputPrams{}, originalSql:{}", outputParams, originalSql);
|
||||
|
||||
|
||||
AnnotationBo sqlMeta = new AnnotationBo();
|
||||
sqlMeta.setKey(AnnotationKey.SQL_METADATA.getCode());
|
||||
sqlMeta.setValue(sqlMetaDataBo.getSql());
|
||||
annotationBoList.add(sqlMeta);
|
||||
|
||||
AnnotationBo checkFail = checkIdentifier (spanAlign, sqlMetaDataBo);
|
||||
if (checkFail != null) {
|
||||
// 실패
|
||||
annotationBoList.add(checkFail);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
AnnotationBo sql = new AnnotationBo();
|
||||
sql.setKey(AnnotationKey.SQL.getCode());
|
||||
sql.setValue(originalSql);
|
||||
annotationBoList.add(sql);
|
||||
|
||||
|
||||
}
|
||||
} else {
|
||||
// TODO 보완해야됨.
|
||||
AnnotationBo api = new AnnotationBo();
|
||||
api.setKey(AnnotationKey.SQL.getCode());
|
||||
api.setValue(collisionSqlHashCodeMessage(hashCode, sqlMetaDataList));
|
||||
annotationBoList.add(api);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private AnnotationBo checkIdentifier(SpanAlign spanAlign, SqlMetaDataBo sqlMetaDataBo) {
|
||||
short agentIdentifier = getAgentIdentifier(spanAlign);
|
||||
short sqlIdentifier = sqlMetaDataBo.getIdentifier();
|
||||
if (agentIdentifier == sqlIdentifier) {
|
||||
return null;
|
||||
}
|
||||
AnnotationBo identifierCheckFail = new AnnotationBo();
|
||||
identifierCheckFail.setKey(AnnotationKey.SQL.getCode());
|
||||
identifierCheckFail.setValue("invalid SqlMetaInfo:" + sqlMetaDataBo);
|
||||
return identifierCheckFail;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private AnnotationBo findAnnotation(List<AnnotationBo> annotationBoList, int key) {
|
||||
for (AnnotationBo annotationBo : annotationBoList) {
|
||||
if (key == annotationBo.getKey()) {
|
||||
return annotationBo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private String collisionSqlHashCodeMessage(int hashCode, List<SqlMetaDataBo> sqlMetaDataList) {
|
||||
// TODO 이거 체크하는 테스트를 따로 만들어야 될듯 하다. 왠간하면 확율상 hashCode 충돌 케이스를 쉽게 만들수 없음.
|
||||
StringBuilder sb = new StringBuilder(64);
|
||||
sb.append("Collision Sql hashCode:");
|
||||
sb.append(hashCode);
|
||||
sb.append('\n');
|
||||
for (int i = 0; i < sqlMetaDataList.size(); i++) {
|
||||
if (i != 0) {
|
||||
sb.append("or\n");
|
||||
}
|
||||
SqlMetaDataBo sqlMetaDataBo = sqlMetaDataList.get(i);
|
||||
sb.append(sqlMetaDataBo.getSql());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getAgentId(SpanAlign spanAlign) {
|
||||
if (spanAlign.isSpan()) {
|
||||
return spanAlign.getSpanBo().getAgentId();
|
||||
} else {
|
||||
return spanAlign.getSpanEventBo().getAgentId();
|
||||
}
|
||||
}
|
||||
|
||||
private short getAgentIdentifier(SpanAlign spanAlign) {
|
||||
if (spanAlign.isSpan()) {
|
||||
return spanAlign.getSpanBo().getAgentIdentifier();
|
||||
} else {
|
||||
return spanAlign.getSpanEventBo().getAgentIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
private void transitionDynamicApiId(List<SpanAlign> spans) {
|
||||
this.transitionAnnotation(spans, new AnnotationReplacementCallback() {
|
||||
@Override
|
||||
public void replacement(SpanAlign spanAlign, List<AnnotationBo> annotationBoList) {
|
||||
AnnotationBo apiIdAnnotation = findAnnotation(annotationBoList, AnnotationKey.API_DID.getCode());
|
||||
if (apiIdAnnotation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AgentInfoBo agentInfoBo = null;
|
||||
try {
|
||||
agentInfoBo = findAgentInfoBoBeforeStartTime(spanAlign);
|
||||
logger.info("{} Agent StartTime found:{}", agentInfoBo.getAgentId(), agentInfoBo);
|
||||
} catch (AgentIdNotFoundException ex) {
|
||||
AnnotationBo agentInfoNotFound = new AnnotationBo();
|
||||
agentInfoNotFound.setKey(AnnotationKey.ERROR_API_METADATA_AGENT_INFO_NOT_FOUND.getCode());
|
||||
agentInfoNotFound.setValue("API-DynamicID not found. Cause:agentInfo not found. agentId:" + ex.getAgentId() + " startTime:" + ex.getStartTime());
|
||||
annotationBoList.add(agentInfoNotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
int apiId = (Integer) apiIdAnnotation.getValue();
|
||||
List<ApiMetaDataBo> apiMetaDataList = apiMetaDataDao.getApiMetaData(agentInfoBo.getAgentId(), agentInfoBo.getIdentifier(), apiId, agentInfoBo.getTimestamp());
|
||||
int size = apiMetaDataList.size();
|
||||
if (size == 0) {
|
||||
AnnotationBo api = new AnnotationBo();
|
||||
api.setKey(AnnotationKey.ERROR_API_METADATA_NOT_FOUND.getCode());
|
||||
api.setValue("API-DynamicID not found. api:" + apiId);
|
||||
annotationBoList.add(api);
|
||||
} else if (size == 1) {
|
||||
ApiMetaDataBo apiMetaDataBo = apiMetaDataList.get(0);
|
||||
AnnotationBo apiMetaData = new AnnotationBo();
|
||||
apiMetaData.setKey(AnnotationKey.API_METADATA.getCode());
|
||||
apiMetaData.setValue(apiMetaDataBo);
|
||||
annotationBoList.add(apiMetaData);
|
||||
|
||||
|
||||
AnnotationBo checkFail = checkIdentifier (spanAlign, apiMetaDataBo);
|
||||
if (checkFail != null) {
|
||||
// 실패
|
||||
annotationBoList.add(checkFail);
|
||||
return;
|
||||
}
|
||||
|
||||
AnnotationBo apiAnnotation = new AnnotationBo();
|
||||
apiAnnotation.setKey(AnnotationKey.API.getCode());
|
||||
String apiInfo = getApiInfo(apiMetaDataBo);
|
||||
apiAnnotation.setValue(apiInfo);
|
||||
annotationBoList.add(apiAnnotation);
|
||||
} else {
|
||||
AnnotationBo apiAnnotation = new AnnotationBo();
|
||||
apiAnnotation.setKey(AnnotationKey.ERROR_API_METADATA_DID_COLLSION.getCode());
|
||||
String collisonMessage = collisionApiDidMessage(apiId, apiMetaDataList);
|
||||
apiAnnotation.setValue(collisonMessage);
|
||||
annotationBoList.add(apiAnnotation);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
private AnnotationBo checkIdentifier(SpanAlign spanAlign, ApiMetaDataBo apiMetaDataBo) {
|
||||
short agentIdentifier = getAgentIdentifier(spanAlign);
|
||||
short sqlIdentifier = apiMetaDataBo.getIdentifier();
|
||||
if (agentIdentifier == sqlIdentifier) {
|
||||
return null;
|
||||
}
|
||||
AnnotationBo identifierCheckFail = new AnnotationBo();
|
||||
identifierCheckFail.setKey(AnnotationKey.ERROR_API_METADATA_IDENTIFIER_CHECK_ERROR.getCode());
|
||||
identifierCheckFail.setValue("invalid ApiMetaInfo:" + apiMetaDataBo);
|
||||
return identifierCheckFail;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private AgentInfoBo findAgentInfoBoBeforeStartTime(SpanAlign spanAlign) {
|
||||
String agentId = getAgentId(spanAlign);
|
||||
long startTime = spanAlign.getSpanBo().getStartTime();
|
||||
AgentInfoBo agentInfoBeforeStartTime = agentInfoDao.findAgentInfoBeforeStartTime(agentId, startTime);
|
||||
if (agentInfoBeforeStartTime == null) {
|
||||
throw new AgentIdNotFoundException(agentId, startTime);
|
||||
}
|
||||
return agentInfoBeforeStartTime;
|
||||
}
|
||||
|
||||
private String collisionApiDidMessage(int apidId, List<ApiMetaDataBo> apiMetaDataList) {
|
||||
// TODO 이거 체크하는 테스트를 따로 만들어야 될듯 하다. 왠간하면 확율상 hashCode 충돌 케이스를 쉽게 만들수 없음.
|
||||
StringBuilder sb = new StringBuilder(64);
|
||||
sb.append("Collision Api DynamicId:");
|
||||
sb.append(apidId);
|
||||
sb.append('\n');
|
||||
for (int i = 0; i < apiMetaDataList.size(); i++) {
|
||||
if (i != 0) {
|
||||
sb.append("or\n");
|
||||
}
|
||||
ApiMetaDataBo apiMetaDataBo = apiMetaDataList.get(i);
|
||||
sb.append(getApiInfo(apiMetaDataBo));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getApiInfo(ApiMetaDataBo apiMetaDataBo) {
|
||||
if (apiMetaDataBo.getLineNumber() != -1) {
|
||||
return apiMetaDataBo.getApiInfo() + ":" + apiMetaDataBo.getLineNumber();
|
||||
} else {
|
||||
return apiMetaDataBo.getApiInfo();
|
||||
}
|
||||
}
|
||||
|
||||
private void transitionApiId(List<SpanAlign> spans) {
|
||||
this.transitionAnnotation(spans, new AnnotationReplacementCallback() {
|
||||
@Override
|
||||
public void replacement(SpanAlign spanAlign, List<AnnotationBo> annotationBoList) {
|
||||
AnnotationBo apiIdAnnotation = findAnnotation(annotationBoList, AnnotationKey.API_ID.getCode());
|
||||
if (apiIdAnnotation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
MethodMapping methodMapping = ApiMappingTable.findMethodMapping((Integer) apiIdAnnotation.getValue());
|
||||
if (methodMapping == null) {
|
||||
return;
|
||||
}
|
||||
String className = methodMapping.getClassMapping().getClassName();
|
||||
String methodName = methodMapping.getMethodName();
|
||||
String[] parameterType = methodMapping.getParameterType();
|
||||
String[] parameterName = methodMapping.getParameterName();
|
||||
String args = ApiUtils.mergeParameterVariableNameDescription(parameterType, parameterName);
|
||||
AnnotationBo api = new AnnotationBo();
|
||||
api.setKey(AnnotationKey.API.getCode());
|
||||
api.setValue(className + "." + methodName + args);
|
||||
annotationBoList.add(api);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static interface AnnotationReplacementCallback {
|
||||
void replacement(SpanAlign spanAlign, List<AnnotationBo> annotationBoList);
|
||||
}
|
||||
|
||||
private List<SpanAlign> order(List<SpanBo> spans) {
|
||||
SpanAligner2 spanAligner = new SpanAligner2(spans);
|
||||
return spanAligner.sort();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SpanBo> selectRequestMetadata(RequestMetadataQuery query) {
|
||||
List<List<SpanBo>> selectedSpans = traceDao.selectSpans(query.getTraceIds());
|
||||
|
||||
List<SpanBo> result = new ArrayList<SpanBo>(query.size());
|
||||
|
||||
// 조회된 녀석들 중에서 UUID, starttime, responseTime이 같은것들만 골라냄.
|
||||
for (List<SpanBo> spans : selectedSpans) {
|
||||
for (SpanBo span : spans) {
|
||||
// check UUID and time
|
||||
if (query.isExists(span.getMostTraceId(), span.getLeastTraceId(), span.getCollectorAcceptTime(), span.getElapsed())) {
|
||||
result.add(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO 일단 임시로...
|
||||
Collections.sort(result, new Comparator<SpanBo>() {
|
||||
private void transitionSqlId(final List<SpanAlign> spans) {
|
||||
this.transitionAnnotation(spans, new AnnotationReplacementCallback() {
|
||||
@Override
|
||||
public int compare(SpanBo o1, SpanBo o2) {
|
||||
if (o1.getException() != 0 && o2.getException() != 0) {
|
||||
return o2.getElapsed() - o1.getElapsed();
|
||||
} else if (o1.getException() != 0) {
|
||||
return -1;
|
||||
} else if (o2.getException() != 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return o2.getElapsed() - o1.getElapsed();
|
||||
public void replacement(SpanAlign spanAlign, List<AnnotationBo> annotationBoList) {
|
||||
AnnotationBo sqlIdAnnotation = findAnnotation(annotationBoList, AnnotationKey.SQL_ID.getCode());
|
||||
if (sqlIdAnnotation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AgentInfoBo agentInfoBo = null;
|
||||
try {
|
||||
agentInfoBo = findAgentInfoBoBeforeStartTime(spanAlign);
|
||||
logger.info("{} Agent StartTime found:{}", agentInfoBo.getAgentId(), agentInfoBo);
|
||||
} catch (AgentIdNotFoundException ex) {
|
||||
AnnotationBo agentInfoNotFound = new AnnotationBo();
|
||||
agentInfoNotFound.setKey(AnnotationKey.SQL.getCode());
|
||||
agentInfoNotFound.setValue("SQL-ID not found. Cause:agentInfo not found. agentId:" + ex.getAgentId() + " startTime:" + ex.getStartTime());
|
||||
annotationBoList.add(agentInfoNotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO 일단 시간까지 조회는 하지 말고 하자.
|
||||
// 미리 sqlMetaDataList를 indentifier로 필터치는 로직이 더 좋을것으로 생각됨.
|
||||
int hashCode = (Integer) sqlIdAnnotation.getValue();
|
||||
List<SqlMetaDataBo> sqlMetaDataList = sqlMetaDataDao.getSqlMetaData(agentInfoBo.getAgentId(), agentInfoBo.getIdentifier(), hashCode, agentInfoBo.getTimestamp());
|
||||
int size = sqlMetaDataList.size();
|
||||
if (size == 0) {
|
||||
AnnotationBo api = new AnnotationBo();
|
||||
api.setKey(AnnotationKey.SQL.getCode());
|
||||
api.setValue("SQL-ID not found hashCode:" + hashCode);
|
||||
annotationBoList.add(api);
|
||||
} else if (size == 1) {
|
||||
AnnotationBo sqlParamAnnotationBo = findAnnotation(annotationBoList, AnnotationKey.SQL_PARAM.getCode());
|
||||
final SqlMetaDataBo sqlMetaDataBo = sqlMetaDataList.get(0);
|
||||
if (sqlParamAnnotationBo == null) {
|
||||
AnnotationBo sqlMeta = new AnnotationBo();
|
||||
sqlMeta.setKey(AnnotationKey.SQL_METADATA.getCode());
|
||||
sqlMeta.setValue(sqlMetaDataBo.getSql());
|
||||
annotationBoList.add(sqlMeta);
|
||||
|
||||
AnnotationBo checkFail = checkIdentifier(spanAlign, sqlMetaDataBo);
|
||||
if (checkFail != null) {
|
||||
// 실패
|
||||
annotationBoList.add(checkFail);
|
||||
return;
|
||||
}
|
||||
|
||||
AnnotationBo sql = new AnnotationBo();
|
||||
sql.setKey(AnnotationKey.SQL.getCode());
|
||||
sql.setValue(sqlMetaDataBo.getSql());
|
||||
annotationBoList.add(sql);
|
||||
} else {
|
||||
logger.debug("sqlMetaDataBo:{}", sqlMetaDataBo);
|
||||
String outputParams = (String) sqlParamAnnotationBo.getValue();
|
||||
List<String> parsedOutputParams = outputParameterParser.parseOutputParameter(outputParams);
|
||||
logger.debug("outputPrams:{}, parsedOutputPrams:{}", outputParams, parsedOutputParams);
|
||||
String originalSql = sqlParser.combineOutputParams(sqlMetaDataBo.getSql(), parsedOutputParams);
|
||||
logger.debug("outputPrams{}, originalSql:{}", outputParams, originalSql);
|
||||
|
||||
AnnotationBo sqlMeta = new AnnotationBo();
|
||||
sqlMeta.setKey(AnnotationKey.SQL_METADATA.getCode());
|
||||
sqlMeta.setValue(sqlMetaDataBo.getSql());
|
||||
annotationBoList.add(sqlMeta);
|
||||
|
||||
AnnotationBo checkFail = checkIdentifier(spanAlign, sqlMetaDataBo);
|
||||
if (checkFail != null) {
|
||||
// 실패
|
||||
annotationBoList.add(checkFail);
|
||||
return;
|
||||
}
|
||||
|
||||
AnnotationBo sql = new AnnotationBo();
|
||||
sql.setKey(AnnotationKey.SQL.getCode());
|
||||
sql.setValue(originalSql);
|
||||
annotationBoList.add(sql);
|
||||
|
||||
}
|
||||
} else {
|
||||
// TODO 보완해야됨.
|
||||
AnnotationBo api = new AnnotationBo();
|
||||
api.setKey(AnnotationKey.SQL.getCode());
|
||||
api.setValue(collisionSqlHashCodeMessage(hashCode, sqlMetaDataList));
|
||||
annotationBoList.add(api);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private AnnotationBo checkIdentifier(SpanAlign spanAlign, SqlMetaDataBo sqlMetaDataBo) {
|
||||
short agentIdentifier = getAgentIdentifier(spanAlign);
|
||||
short sqlIdentifier = sqlMetaDataBo.getIdentifier();
|
||||
if (agentIdentifier == sqlIdentifier) {
|
||||
return null;
|
||||
}
|
||||
AnnotationBo identifierCheckFail = new AnnotationBo();
|
||||
identifierCheckFail.setKey(AnnotationKey.SQL.getCode());
|
||||
identifierCheckFail.setValue("invalid SqlMetaInfo:" + sqlMetaDataBo);
|
||||
return identifierCheckFail;
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private AnnotationBo findAnnotation(List<AnnotationBo> annotationBoList, int key) {
|
||||
for (AnnotationBo annotationBo : annotationBoList) {
|
||||
if (key == annotationBo.getKey()) {
|
||||
return annotationBo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String collisionSqlHashCodeMessage(int hashCode, List<SqlMetaDataBo> sqlMetaDataList) {
|
||||
// TODO 이거 체크하는 테스트를 따로 만들어야 될듯 하다. 왠간하면 확율상 hashCode 충돌 케이스를 쉽게 만들수 없음.
|
||||
StringBuilder sb = new StringBuilder(64);
|
||||
sb.append("Collision Sql hashCode:");
|
||||
sb.append(hashCode);
|
||||
sb.append('\n');
|
||||
for (int i = 0; i < sqlMetaDataList.size(); i++) {
|
||||
if (i != 0) {
|
||||
sb.append("or\n");
|
||||
}
|
||||
SqlMetaDataBo sqlMetaDataBo = sqlMetaDataList.get(i);
|
||||
sb.append(sqlMetaDataBo.getSql());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getAgentId(SpanAlign spanAlign) {
|
||||
if (spanAlign.isSpan()) {
|
||||
return spanAlign.getSpanBo().getAgentId();
|
||||
} else {
|
||||
return spanAlign.getSpanEventBo().getAgentId();
|
||||
}
|
||||
}
|
||||
|
||||
private short getAgentIdentifier(SpanAlign spanAlign) {
|
||||
if (spanAlign.isSpan()) {
|
||||
return spanAlign.getSpanBo().getAgentIdentifier();
|
||||
} else {
|
||||
return spanAlign.getSpanEventBo().getAgentIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
private void transitionDynamicApiId(List<SpanAlign> spans) {
|
||||
this.transitionAnnotation(spans, new AnnotationReplacementCallback() {
|
||||
@Override
|
||||
public void replacement(SpanAlign spanAlign, List<AnnotationBo> annotationBoList) {
|
||||
AnnotationBo apiIdAnnotation = findAnnotation(annotationBoList, AnnotationKey.API_DID.getCode());
|
||||
if (apiIdAnnotation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AgentInfoBo agentInfoBo = null;
|
||||
try {
|
||||
agentInfoBo = findAgentInfoBoBeforeStartTime(spanAlign);
|
||||
logger.info("{} Agent StartTime found:{}", agentInfoBo.getAgentId(), agentInfoBo);
|
||||
} catch (AgentIdNotFoundException ex) {
|
||||
AnnotationBo agentInfoNotFound = new AnnotationBo();
|
||||
agentInfoNotFound.setKey(AnnotationKey.ERROR_API_METADATA_AGENT_INFO_NOT_FOUND.getCode());
|
||||
agentInfoNotFound.setValue("API-DynamicID not found. Cause:agentInfo not found. agentId:" + ex.getAgentId() + " startTime:" + ex.getStartTime());
|
||||
annotationBoList.add(agentInfoNotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
int apiId = (Integer) apiIdAnnotation.getValue();
|
||||
List<ApiMetaDataBo> apiMetaDataList = apiMetaDataDao.getApiMetaData(agentInfoBo.getAgentId(), agentInfoBo.getIdentifier(), apiId, agentInfoBo.getTimestamp());
|
||||
int size = apiMetaDataList.size();
|
||||
if (size == 0) {
|
||||
AnnotationBo api = new AnnotationBo();
|
||||
api.setKey(AnnotationKey.ERROR_API_METADATA_NOT_FOUND.getCode());
|
||||
api.setValue("API-DynamicID not found. api:" + apiId);
|
||||
annotationBoList.add(api);
|
||||
} else if (size == 1) {
|
||||
ApiMetaDataBo apiMetaDataBo = apiMetaDataList.get(0);
|
||||
AnnotationBo apiMetaData = new AnnotationBo();
|
||||
apiMetaData.setKey(AnnotationKey.API_METADATA.getCode());
|
||||
apiMetaData.setValue(apiMetaDataBo);
|
||||
annotationBoList.add(apiMetaData);
|
||||
|
||||
AnnotationBo checkFail = checkIdentifier(spanAlign, apiMetaDataBo);
|
||||
if (checkFail != null) {
|
||||
// 실패
|
||||
annotationBoList.add(checkFail);
|
||||
return;
|
||||
}
|
||||
|
||||
AnnotationBo apiAnnotation = new AnnotationBo();
|
||||
apiAnnotation.setKey(AnnotationKey.API.getCode());
|
||||
String apiInfo = getApiInfo(apiMetaDataBo);
|
||||
apiAnnotation.setValue(apiInfo);
|
||||
annotationBoList.add(apiAnnotation);
|
||||
} else {
|
||||
AnnotationBo apiAnnotation = new AnnotationBo();
|
||||
apiAnnotation.setKey(AnnotationKey.ERROR_API_METADATA_DID_COLLSION.getCode());
|
||||
String collisonMessage = collisionApiDidMessage(apiId, apiMetaDataList);
|
||||
apiAnnotation.setValue(collisonMessage);
|
||||
annotationBoList.add(apiAnnotation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private AnnotationBo checkIdentifier(SpanAlign spanAlign, ApiMetaDataBo apiMetaDataBo) {
|
||||
short agentIdentifier = getAgentIdentifier(spanAlign);
|
||||
short sqlIdentifier = apiMetaDataBo.getIdentifier();
|
||||
if (agentIdentifier == sqlIdentifier) {
|
||||
return null;
|
||||
}
|
||||
AnnotationBo identifierCheckFail = new AnnotationBo();
|
||||
identifierCheckFail.setKey(AnnotationKey.ERROR_API_METADATA_IDENTIFIER_CHECK_ERROR.getCode());
|
||||
identifierCheckFail.setValue("invalid ApiMetaInfo:" + apiMetaDataBo);
|
||||
return identifierCheckFail;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private AgentInfoBo findAgentInfoBoBeforeStartTime(SpanAlign spanAlign) {
|
||||
String agentId = getAgentId(spanAlign);
|
||||
long startTime = spanAlign.getSpanBo().getStartTime();
|
||||
AgentInfoBo agentInfoBeforeStartTime = agentInfoDao.findAgentInfoBeforeStartTime(agentId, startTime);
|
||||
if (agentInfoBeforeStartTime == null) {
|
||||
throw new AgentIdNotFoundException(agentId, startTime);
|
||||
}
|
||||
return agentInfoBeforeStartTime;
|
||||
}
|
||||
|
||||
private String collisionApiDidMessage(int apidId, List<ApiMetaDataBo> apiMetaDataList) {
|
||||
// TODO 이거 체크하는 테스트를 따로 만들어야 될듯 하다. 왠간하면 확율상 hashCode 충돌 케이스를 쉽게 만들수 없음.
|
||||
StringBuilder sb = new StringBuilder(64);
|
||||
sb.append("Collision Api DynamicId:");
|
||||
sb.append(apidId);
|
||||
sb.append('\n');
|
||||
for (int i = 0; i < apiMetaDataList.size(); i++) {
|
||||
if (i != 0) {
|
||||
sb.append("or\n");
|
||||
}
|
||||
ApiMetaDataBo apiMetaDataBo = apiMetaDataList.get(i);
|
||||
sb.append(getApiInfo(apiMetaDataBo));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getApiInfo(ApiMetaDataBo apiMetaDataBo) {
|
||||
if (apiMetaDataBo.getLineNumber() != -1) {
|
||||
return apiMetaDataBo.getApiInfo() + ":" + apiMetaDataBo.getLineNumber();
|
||||
} else {
|
||||
return apiMetaDataBo.getApiInfo();
|
||||
}
|
||||
}
|
||||
|
||||
private void transitionApiId(List<SpanAlign> spans) {
|
||||
this.transitionAnnotation(spans, new AnnotationReplacementCallback() {
|
||||
@Override
|
||||
public void replacement(SpanAlign spanAlign, List<AnnotationBo> annotationBoList) {
|
||||
AnnotationBo apiIdAnnotation = findAnnotation(annotationBoList, AnnotationKey.API_ID.getCode());
|
||||
if (apiIdAnnotation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
MethodMapping methodMapping = ApiMappingTable.findMethodMapping((Integer) apiIdAnnotation.getValue());
|
||||
if (methodMapping == null) {
|
||||
return;
|
||||
}
|
||||
String className = methodMapping.getClassMapping().getClassName();
|
||||
String methodName = methodMapping.getMethodName();
|
||||
String[] parameterType = methodMapping.getParameterType();
|
||||
String[] parameterName = methodMapping.getParameterName();
|
||||
String args = ApiUtils.mergeParameterVariableNameDescription(parameterType, parameterName);
|
||||
AnnotationBo api = new AnnotationBo();
|
||||
api.setKey(AnnotationKey.API.getCode());
|
||||
api.setValue(className + "." + methodName + args);
|
||||
annotationBoList.add(api);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static interface AnnotationReplacementCallback {
|
||||
void replacement(SpanAlign spanAlign, List<AnnotationBo> annotationBoList);
|
||||
}
|
||||
|
||||
private List<SpanAlign> order(List<SpanBo> spans) {
|
||||
SpanAligner2 spanAligner = new SpanAligner2(spans);
|
||||
return spanAligner.sort();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package com.nhn.hippo.web.vo;
|
||||
|
||||
import com.profiler.common.util.TraceIdUtils;
|
||||
|
||||
/**
|
||||
* UI로 이 객체 대신 SpanBO를 던진다.
|
||||
*
|
||||
* @author netspider
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
public class RequestMetadata {
|
||||
|
||||
private final String traceId;
|
||||
private final long startTime;
|
||||
private final int elapsed;
|
||||
private final String application;
|
||||
|
||||
public RequestMetadata(long mostTraceId, long leastTraceId, long startTime, int elapsed, String application) {
|
||||
this.traceId = TraceIdUtils.formatString(mostTraceId, leastTraceId);
|
||||
this.startTime = startTime;
|
||||
this.elapsed = elapsed;
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
public String getTraceId() {
|
||||
return traceId;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public int getElapsed() {
|
||||
return elapsed;
|
||||
}
|
||||
|
||||
public String getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(traceId);
|
||||
sb.append(startTime);
|
||||
sb.append(elapsed);
|
||||
sb.append(application);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -13,12 +13,12 @@ import java.util.Set;
|
||||
* @author netspider
|
||||
*
|
||||
*/
|
||||
public class RequestMetadataQuery {
|
||||
public class TransactionMetadataQuery {
|
||||
|
||||
private final Map<QueryCondition, Object> queryConditions;
|
||||
|
||||
public RequestMetadataQuery() {
|
||||
queryConditions = new HashMap<RequestMetadataQuery.QueryCondition, Object>();
|
||||
public TransactionMetadataQuery() {
|
||||
queryConditions = new HashMap<TransactionMetadataQuery.QueryCondition, Object>();
|
||||
}
|
||||
|
||||
public void addQueryCondition(String traceId, long time, int responseTime) {
|
||||
Reference in New Issue
Block a user