[강운덕] [PINPOINT-266] was의 responseTime 데이터를 실제 데이터를 사용하도록 함.

git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-web/trunk@3271 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
Woonduk Kang
2014-02-06 06:56:41 +00:00
parent dfd27b4588
commit f78d461df3
9 changed files with 185 additions and 126 deletions
@@ -3,8 +3,8 @@ package com.nhn.pinpoint.web.applicationmap;
import java.util.*;
import com.nhn.pinpoint.web.applicationmap.rawdata.HostList;
import com.nhn.pinpoint.web.applicationmap.rawdata.ResponseHistogram;
import com.nhn.pinpoint.web.service.NodeId;
import com.nhn.pinpoint.web.vo.ResponseHistogramSummary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,7 +32,7 @@ public class Node implements JsonSerializable {
private final HostList hostList = new HostList();
private final Set<AgentInfoBo> agentSet = new HashSet<AgentInfoBo>();
private ResponseHistogram responseHistogram;
private ResponseHistogramSummary responseHistogramSummary;
public Node(NodeId id, String applicationName, ServiceType serviceType, Set<AgentInfoBo> agentSet) {
@@ -147,7 +147,13 @@ public class Node implements JsonSerializable {
return serviceType;
}
public ResponseHistogramSummary getResponseHistogramSummary() {
return responseHistogramSummary;
}
public void setResponseHistogramSummary(ResponseHistogramSummary responseHistogramSummary) {
this.responseHistogramSummary = responseHistogramSummary;
}
@Override
public String getJson() {
@@ -1,6 +1,8 @@
package com.nhn.pinpoint.web.dao;
import com.nhn.pinpoint.web.applicationmap.rawdata.TransactionFlowStatistics;
import com.nhn.pinpoint.web.vo.Application;
import com.nhn.pinpoint.web.vo.RawResponseTime;
import java.util.List;
import java.util.Map;
@@ -11,6 +13,6 @@ import java.util.Map;
*
*/
public interface MapResponseDao {
List<TransactionFlowStatistics> selectResponseTime(String applicationName, short applicationServiceType, long from, long to);
List<RawResponseTime> selectResponseTime(Application application, long from, long to);
}
@@ -5,14 +5,14 @@ import com.nhn.pinpoint.common.hbase.HbaseOperations2;
import com.nhn.pinpoint.common.util.ApplicationMapStatisticsUtils;
import com.nhn.pinpoint.common.util.TimeSlot;
import com.nhn.pinpoint.web.applicationmap.rawdata.TransactionFlowStatistics;
import com.nhn.pinpoint.web.applicationmap.rawdata.TransactionFlowStatisticsKey;
import com.nhn.pinpoint.web.dao.MapResponseDao;
import com.nhn.pinpoint.web.mapper.ApplicationMapLinkStatisticsMapper;
import com.nhn.pinpoint.web.vo.Application;
import com.nhn.pinpoint.web.vo.RawResponseTime;
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;
@@ -21,103 +21,69 @@ import java.text.SimpleDateFormat;
import java.util.*;
/**
*
* @author netspider
* @author emeroad
*
*/
@Repository
public class HbaseMapResponseTimeDao implements MapResponseDao {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private int scanCacheSize = 40;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private HbaseOperations2 hbaseOperations2;
private final String tableName = HBaseTables.APPLICATION_MAP_STATISTICS_SELF;
private int scanCacheSize = 40;
@Autowired
private RowMapper<RawResponseTime> responseTimeMapper;
@Autowired
private HbaseOperations2 hbaseOperations2;
@Override
public List<TransactionFlowStatistics> selectResponseTime(String applicationName, short applicationServiceType, long from, long to) {
return Collections.emptyList();
public List<RawResponseTime> selectResponseTime(Application application, long from, long to) {
if (application == null) {
throw new NullPointerException("application must not be null");
}
if (logger.isDebugEnabled()) {
logger.debug("selectResponseTime applicationName:{}, from:{}, to:{}", application, from, to);
}
Scan scan = createScan(application, from, to);
List<RawResponseTime> rawResponseTimeList = hbaseOperations2.find(tableName, scan, responseTimeMapper);
if (logger.isDebugEnabled()) {
logger.debug("row:{}", rawResponseTimeList.size());
for (RawResponseTime rawResponseTime : rawResponseTimeList) {
logger.debug("rawResponseTime:{}", rawResponseTime);
}
}
return rawResponseTimeList;
}
// @Override
// public List<TransactionFlowStatistics> selectCallee(String callerApplicationName, short callerServiceType, long from, long to) {
// Scan scan = createScan(callerApplicationName, callerServiceType, from, to);
// final List<List<TransactionFlowStatistics>> foundListList = hbaseOperations2.find(HBaseTables.APPLICATION_MAP_STATISTICS_CALLEE, scan, applicationMapStatisticsCalleeMapper);
//
// if (foundListList.isEmpty()) {
// logger.debug("There's no callee data. {}, {}, {}, {}", callerApplicationName, callerServiceType, from, to);
// }
//
// return merge(foundListList);
// }
//
// private List<TransactionFlowStatistics> merge(List<List<TransactionFlowStatistics>> foundListList) {
// final Map<TransactionFlowStatisticsKey, TransactionFlowStatistics> result = new HashMap<TransactionFlowStatisticsKey, TransactionFlowStatistics>();
//
// for (List<TransactionFlowStatistics> foundList : foundListList) {
// for (TransactionFlowStatistics found : foundList) {
// final TransactionFlowStatisticsKey key = new TransactionFlowStatisticsKey(found);
// final TransactionFlowStatistics find = result.get(key);
// if (find != null) {
// find.add(found);
// } else {
// result.put(key, found);
// }
// }
// }
//
//
// return new ArrayList<TransactionFlowStatistics>(result.values());
// }
private Scan createScan(Application application, 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)));
}
// timestamp가 reverse되었기 때문에 start, end를 바꿔서 조회.
byte[] startKey = ApplicationMapStatisticsUtils.makeRowKey(application.getApplicationName(), application.getServiceTypeCode(), endTime);
byte[] endKey = ApplicationMapStatisticsUtils.makeRowKey(application.getApplicationName(), application.getServiceTypeCode(), startTime);
final Scan scan = new Scan();
scan.setCaching(this.scanCacheSize);
scan.setStartRow(startKey);
scan.setStopRow(endKey);
scan.addFamily(HBaseTables.APPLICATION_MAP_STATISTICS_SELF_CF_COUNTER);
scan.setId("ApplicationSelfScan");
return scan;
}
/**
* 메인페이지 서버 맵에서 연결선을 선택했을 때 보여주는 통계정보.
*
* @return <pre>
* list [
* map {
* key = timestamp
* value = map {
* key = histogram slot
* value = count
* }
* }
* ]
* </pre>
*/
// @Override
// public List<Map<Long, Map<Short, Long>>> selectCalleeStatistics(String callerApplicationName, short callerServiceType, String calleeApplicationName, short calleeServiceType, long from, long to) {
// if (logger.isDebugEnabled()) {
// logger.debug("selectCalleeStatistics. {}, {}, {}, {}, {}, {}", callerApplicationName, callerServiceType, calleeApplicationName, calleeServiceType, from, to);
// }
// Scan scan = createScan(callerApplicationName, callerServiceType, from, to);
// RowMapper<Map<Long, Map<Short, Long>>> mapper = new ApplicationMapLinkStatisticsMapper(callerApplicationName, callerServiceType, calleeApplicationName, calleeServiceType);
// return hbaseOperations2.find(HBaseTables.APPLICATION_MAP_STATISTICS_CALLEE, scan, mapper);
// }
//
// 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)));
// }
//
// // timestamp가 reverse되었기 때문에 start, end를 바꿔서 조회.
// byte[] startKey = ApplicationMapStatisticsUtils.makeRowKey(applicationName, serviceType, endTime);
// byte[] endKey = ApplicationMapStatisticsUtils.makeRowKey(applicationName, serviceType, startTime);
//
// Scan scan = new Scan();
// scan.setCaching(this.scanCacheSize);
// scan.setStartRow(startKey);
// scan.setStopRow(endKey);
// scan.addFamily(HBaseTables.APPLICATION_MAP_STATISTICS_CALLEE_CF_COUNTER);
// scan.setId("ApplicationStatisticsScan");
//
// return scan;
// }
}
@@ -1,18 +1,20 @@
package com.nhn.pinpoint.web.mapper;
import com.nhn.pinpoint.common.buffer.Buffer;
import com.nhn.pinpoint.common.buffer.FixedBuffer;
import com.nhn.pinpoint.common.hbase.HBaseTables;
import com.nhn.pinpoint.common.util.ApplicationStatisticsUtils;
import com.nhn.pinpoint.common.util.TimeUtils;
import com.nhn.pinpoint.web.vo.RawResponseTime;
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;
/**
* @author emeroad
*/
@Component
public class ResponseTimeMapper implements RowMapper<RawResponseTime> {
@Override
public RawResponseTime mapRow(Result result, int rowNum) throws Exception {
@@ -26,28 +28,26 @@ public class ResponseTimeMapper implements RowMapper<RawResponseTime> {
if (!Bytes.equals(keyValue.getFamily(), HBaseTables.APPLICATION_MAP_STATISTICS_SELF_CF_COUNTER)) {
return rawResponseTime;
}
final byte[] row = keyValue.getRow();
final byte[] value = keyValue.getValue();
recordColumn(rawResponseTime, row, value);
byte[] qualifier = keyValue.getQualifier();
byte[] value = keyValue.getValue();
recordColumn(rawResponseTime, qualifier, value);
}
return rawResponseTime;
}
void recordColumn(RawResponseTime rawResponseTime, byte[] row, byte[] value) {
short slotNumber = Bytes.toShort(row);
void recordColumn(RawResponseTime rawResponseTime, byte[] qualifier, byte[] value) {
short slotNumber = Bytes.toShort(qualifier);
// agentId도 데이터로 같이 엮어야 함.
String agentId = Bytes.toString(row, 2, row.length - 2);
String agentId = Bytes.toString(qualifier, 2, qualifier.length - 2);
long count = Bytes.toLong(value);
rawResponseTime.getHistogram(agentId).addSample(slotNumber, count);
}
private RawResponseTime createRawResponseTime(byte[] rowKey) {
final Buffer rowBuffer = new FixedBuffer(rowKey);
String applicationName = rowBuffer.readPrefixedString();
short serviceType = rowBuffer.readShort();
long time = com.nhn.pinpoint.common.util.TimeUtils.recoveryCurrentTimeMillis(rowBuffer.readLong());
String applicationName = ApplicationStatisticsUtils.getApplicationNameFromRowKey(rowKey);
short serviceType = ApplicationStatisticsUtils.getApplicationTypeFromRowKey(rowKey);
long time = TimeUtils.recoveryCurrentTimeMillis(ApplicationStatisticsUtils.getTimestampFromRowKey(rowKey));
return new RawResponseTime(applicationName, serviceType, time);
}
}
@@ -1,12 +1,13 @@
package com.nhn.pinpoint.web.service;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
import java.util.Set;
import com.nhn.pinpoint.web.applicationmap.ApplicationMapBuilder;
import com.nhn.pinpoint.web.applicationmap.rawdata.ResponseHistogram;
import com.nhn.pinpoint.web.dao.*;
import com.nhn.pinpoint.web.vo.RawResponseTime;
import com.nhn.pinpoint.web.vo.ResponseHistogramSummary;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -17,11 +18,6 @@ import com.nhn.pinpoint.common.ServiceType;
import com.nhn.pinpoint.common.bo.AgentInfoBo;
import com.nhn.pinpoint.web.applicationmap.ApplicationMap;
import com.nhn.pinpoint.web.applicationmap.rawdata.TransactionFlowStatistics;
import com.nhn.pinpoint.web.dao.AgentInfoDao;
import com.nhn.pinpoint.web.dao.ApplicationIndexDao;
import com.nhn.pinpoint.web.dao.ApplicationMapStatisticsCalleeDao;
import com.nhn.pinpoint.web.dao.ApplicationMapStatisticsCallerDao;
import com.nhn.pinpoint.web.dao.HostApplicationMapDao;
import com.nhn.pinpoint.web.vo.Application;
import com.nhn.pinpoint.web.vo.LinkStatistics;
@@ -40,6 +36,9 @@ public class ApplicationMapServiceImpl implements ApplicationMapService {
@Autowired
private AgentInfoDao agentInfoDao;
@Autowired
private MapResponseDao mapResponseDao;
@Autowired
private ApplicationMapStatisticsCallerDao applicationMapStatisticsCallerDao;
@@ -223,13 +222,12 @@ public class ApplicationMapServiceImpl implements ApplicationMapService {
StopWatch watch = new StopWatch("applicationMapWatch");
watch.start();
// 무한 탐색을 방지하기 위한 용도.
// 무한 탐색을 방지하기 위한 용도.
final Set<Node> callerFoundApplications = new HashSet<Node>();
final Set<Node> calleeFoundApplications = new HashSet<Node>();
Set<TransactionFlowStatistics> callee = selectCallee(applicationName, serviceType, from, to, calleeFoundApplications, callerFoundApplications);
logger.debug("Result of finding callee {}", callee);
Set<TransactionFlowStatistics> caller = selectCaller(applicationName, serviceType, from, to, calleeFoundApplications, callerFoundApplications);
logger.debug("Result of finding caller {}", caller);
@@ -238,14 +236,41 @@ public class ApplicationMapServiceImpl implements ApplicationMapService {
data.addAll(caller);
ApplicationMap map = new ApplicationMapBuilder().build(data);
appendWasResponseTime(map, from, to);
watch.stop();
logger.info("Fetch applicationmap elapsed. {}ms", watch.getLastTaskTimeMillis());
return map;
}
@Override
private void appendWasResponseTime(ApplicationMap map, long from, long to) {
List<com.nhn.pinpoint.web.applicationmap.Node> nodes = map.getNodes();
for (com.nhn.pinpoint.web.applicationmap.Node node : nodes) {
final boolean was = node.getServiceType().isWas();
if (!was) {
continue;
}
final Application application = new Application(node.getApplicationName(), node.getServiceType());
final List<RawResponseTime> responseHistogram = this.mapResponseDao.selectResponseTime(application, from, to);
ResponseHistogramSummary histogramSummary = createHistogramSummary(application, responseHistogram);
node.setResponseHistogramSummary(histogramSummary);
}
}
private ResponseHistogramSummary createHistogramSummary(Application application, List<RawResponseTime> responseHistogram) {
final ResponseHistogramSummary summary = new ResponseHistogramSummary(application);
for (RawResponseTime rawResponseTime : responseHistogram) {
final List<ResponseHistogram> responseHistogramList = rawResponseTime.getResponseHistogramList();
for (ResponseHistogram histogram : responseHistogramList) {
summary.addTotal(histogram);
}
}
return summary;
}
@Override
public LinkStatistics linkStatistics(long from, long to, String srcApplicationName, short srcServiceType, String destApplicationName, short destServiceType) {
if (srcApplicationName == null) {
throw new NullPointerException("srcApplicationName must not be null");
@@ -10,7 +10,21 @@ import com.nhn.pinpoint.common.ServiceType;
*/
public class Application {
private final String applicationName;
private final ServiceType serviceType;
private final ServiceType serviceType;
// undefine일 경우 추적이 쉽도록 별도 데이터를 보관한다.
private final short code;
public Application(String applicationName, ServiceType serviceType) {
if (applicationName == null) {
throw new NullPointerException("applicationName must not be null");
}
if (serviceType == null) {
throw new NullPointerException("serviceType must not be null");
}
this.applicationName = applicationName;
this.serviceType = serviceType;
this.code = serviceType.getCode();
}
public Application(String applicationName, short serviceType) {
if (applicationName == null) {
@@ -18,6 +32,7 @@ public class Application {
}
this.applicationName = applicationName;
this.serviceType = ServiceType.findServiceType(serviceType);
this.code = serviceType;
}
public String getApplicationName() {
@@ -29,7 +44,7 @@ public class Application {
}
public short getServiceTypeCode() {
return serviceType.getCode();
return code;
}
@Override
@@ -54,6 +69,6 @@ public class Application {
@Override
public String toString() {
return applicationName + "(" + serviceType + ")";
return applicationName + "(" + serviceType + ":" + code + ")";
}
}
@@ -3,8 +3,7 @@ package com.nhn.pinpoint.web.vo;
import com.nhn.pinpoint.web.applicationmap.rawdata.*;
import com.nhn.pinpoint.web.applicationmap.rawdata.ResponseHistogram;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/**
* @author emeroad
@@ -44,7 +43,17 @@ public class RawResponseTime {
return newHistogram;
}
public ResponseHistogram getTotalResponseHistogram() {
throw new UnsupportedOperationException();
public List<ResponseHistogram> getResponseHistogramList() {
return new ArrayList<ResponseHistogram>(responseHistogramMap.values());
}
@Override
public String toString() {
return "RawResponseTime{" +
"applicationName='" + applicationName + '\'' +
", applicationServiceType=" + applicationServiceType +
", timeSlot=" + timeSlot +
", responseHistogramMap=" + responseHistogramMap +
'}';
}
}
@@ -0,0 +1,33 @@
package com.nhn.pinpoint.web.vo;
import com.nhn.pinpoint.web.applicationmap.rawdata.*;
import com.nhn.pinpoint.web.applicationmap.rawdata.ResponseHistogram;
/**
* @author emeroad
*/
public class ResponseHistogramSummary {
private Application application;
private com.nhn.pinpoint.web.applicationmap.rawdata.ResponseHistogram total;
public ResponseHistogramSummary(Application application) {
if (application == null) {
throw new NullPointerException("application must not be null");
}
this.application = application;
this.total = new ResponseHistogram(application.getServiceType());
}
public void addTotal(ResponseHistogram histogram) {
if (histogram == null) {
throw new NullPointerException("histogram must not be null");
}
this.total.add(histogram);
}
public ResponseHistogram getTotal() {
return total;
}
}
@@ -32,6 +32,9 @@
"serviceTypeCode" : "${node.serviceType.code}",
"terminal" : "${node.serviceType.terminal}",
"isWas" : ${node.serviceType.was},
<c:if test="${node.serviceType.was}" >
"histogram" : ${node.responseHistogramSummary.total.json},
</c:if>
"serverList" : {
<c:if test="${node.serviceType.desc != 'UNKNOWN'}">
<c:forEach items="${node.serverInstanceList}" var="serverInstance" varStatus="status5">