From f78d461df3a33373e209ecebd47564dbcb93fd05 Mon Sep 17 00:00:00 2001 From: Woonduk Kang Date: Thu, 6 Feb 2014 06:56:41 +0000 Subject: [PATCH] =?UTF-8?q?[=EA=B0=95=EC=9A=B4=EB=8D=95]=20[PINPOINT-266]?= =?UTF-8?q?=20was=EC=9D=98=20responseTime=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=A5=BC=20=EC=8B=A4=EC=A0=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0?= =?UTF-8?q?=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=ED=95=A8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-web/trunk@3271 84d0f5b1-2673-498c-a247-62c4ff18d310 --- .../nhn/pinpoint/web/applicationmap/Node.java | 10 +- .../nhn/pinpoint/web/dao/MapResponseDao.java | 4 +- .../dao/hbase/HbaseMapResponseTimeDao.java | 144 +++++++----------- .../web/mapper/ResponseTimeMapper.java | 26 ++-- .../service/ApplicationMapServiceImpl.java | 53 +++++-- .../com/nhn/pinpoint/web/vo/Application.java | 21 ++- .../nhn/pinpoint/web/vo/RawResponseTime.java | 17 ++- .../web/vo/ResponseHistogramSummary.java | 33 ++++ .../webapp/WEB-INF/views/applicationmap.jsp | 3 + 9 files changed, 185 insertions(+), 126 deletions(-) create mode 100644 src/main/java/com/nhn/pinpoint/web/vo/ResponseHistogramSummary.java diff --git a/src/main/java/com/nhn/pinpoint/web/applicationmap/Node.java b/src/main/java/com/nhn/pinpoint/web/applicationmap/Node.java index 3797fbbe2..1c78f1535 100644 --- a/src/main/java/com/nhn/pinpoint/web/applicationmap/Node.java +++ b/src/main/java/com/nhn/pinpoint/web/applicationmap/Node.java @@ -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 agentSet = new HashSet(); - private ResponseHistogram responseHistogram; + private ResponseHistogramSummary responseHistogramSummary; public Node(NodeId id, String applicationName, ServiceType serviceType, Set 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() { diff --git a/src/main/java/com/nhn/pinpoint/web/dao/MapResponseDao.java b/src/main/java/com/nhn/pinpoint/web/dao/MapResponseDao.java index dcc858123..339e83503 100644 --- a/src/main/java/com/nhn/pinpoint/web/dao/MapResponseDao.java +++ b/src/main/java/com/nhn/pinpoint/web/dao/MapResponseDao.java @@ -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 selectResponseTime(String applicationName, short applicationServiceType, long from, long to); + List selectResponseTime(Application application, long from, long to); } diff --git a/src/main/java/com/nhn/pinpoint/web/dao/hbase/HbaseMapResponseTimeDao.java b/src/main/java/com/nhn/pinpoint/web/dao/hbase/HbaseMapResponseTimeDao.java index ef96a36be..559cc12ab 100644 --- a/src/main/java/com/nhn/pinpoint/web/dao/hbase/HbaseMapResponseTimeDao.java +++ b/src/main/java/com/nhn/pinpoint/web/dao/hbase/HbaseMapResponseTimeDao.java @@ -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 responseTimeMapper; + + @Autowired + private HbaseOperations2 hbaseOperations2; @Override - public List selectResponseTime(String applicationName, short applicationServiceType, long from, long to) { - return Collections.emptyList(); + public List 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 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 selectCallee(String callerApplicationName, short callerServiceType, long from, long to) { -// Scan scan = createScan(callerApplicationName, callerServiceType, from, to); -// final List> 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 merge(List> foundListList) { -// final Map result = new HashMap(); -// -// for (List 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(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
-	 * list [
-	 *     map {
-	 *         key = timestamp
-	 *         value = map {
-	 *             key = histogram slot
-	 *             value = count
-	 *         }
-	 *     }
-	 * ]
-	 * 
- */ -// @Override -// public List>> 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>> 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; -// } } diff --git a/src/main/java/com/nhn/pinpoint/web/mapper/ResponseTimeMapper.java b/src/main/java/com/nhn/pinpoint/web/mapper/ResponseTimeMapper.java index 9fe5f206a..8509c3004 100644 --- a/src/main/java/com/nhn/pinpoint/web/mapper/ResponseTimeMapper.java +++ b/src/main/java/com/nhn/pinpoint/web/mapper/ResponseTimeMapper.java @@ -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 { @Override public RawResponseTime mapRow(Result result, int rowNum) throws Exception { @@ -26,28 +28,26 @@ public class ResponseTimeMapper implements RowMapper { 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); } } diff --git a/src/main/java/com/nhn/pinpoint/web/service/ApplicationMapServiceImpl.java b/src/main/java/com/nhn/pinpoint/web/service/ApplicationMapServiceImpl.java index 800f64166..452becef6 100644 --- a/src/main/java/com/nhn/pinpoint/web/service/ApplicationMapServiceImpl.java +++ b/src/main/java/com/nhn/pinpoint/web/service/ApplicationMapServiceImpl.java @@ -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 callerFoundApplications = new HashSet(); final Set calleeFoundApplications = new HashSet(); - Set callee = selectCallee(applicationName, serviceType, from, to, calleeFoundApplications, callerFoundApplications); logger.debug("Result of finding callee {}", callee); - + Set 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 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 responseHistogram = this.mapResponseDao.selectResponseTime(application, from, to); + ResponseHistogramSummary histogramSummary = createHistogramSummary(application, responseHistogram); + node.setResponseHistogramSummary(histogramSummary); + } + + } + + private ResponseHistogramSummary createHistogramSummary(Application application, List responseHistogram) { + final ResponseHistogramSummary summary = new ResponseHistogramSummary(application); + for (RawResponseTime rawResponseTime : responseHistogram) { + final List 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"); diff --git a/src/main/java/com/nhn/pinpoint/web/vo/Application.java b/src/main/java/com/nhn/pinpoint/web/vo/Application.java index 14d7c6e65..1e915abe9 100644 --- a/src/main/java/com/nhn/pinpoint/web/vo/Application.java +++ b/src/main/java/com/nhn/pinpoint/web/vo/Application.java @@ -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 + ")"; } } diff --git a/src/main/java/com/nhn/pinpoint/web/vo/RawResponseTime.java b/src/main/java/com/nhn/pinpoint/web/vo/RawResponseTime.java index 4fd9d536c..d47cb0d6e 100644 --- a/src/main/java/com/nhn/pinpoint/web/vo/RawResponseTime.java +++ b/src/main/java/com/nhn/pinpoint/web/vo/RawResponseTime.java @@ -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 getResponseHistogramList() { + return new ArrayList(responseHistogramMap.values()); + } + + @Override + public String toString() { + return "RawResponseTime{" + + "applicationName='" + applicationName + '\'' + + ", applicationServiceType=" + applicationServiceType + + ", timeSlot=" + timeSlot + + ", responseHistogramMap=" + responseHistogramMap + + '}'; } } diff --git a/src/main/java/com/nhn/pinpoint/web/vo/ResponseHistogramSummary.java b/src/main/java/com/nhn/pinpoint/web/vo/ResponseHistogramSummary.java new file mode 100644 index 000000000..973afeb7d --- /dev/null +++ b/src/main/java/com/nhn/pinpoint/web/vo/ResponseHistogramSummary.java @@ -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; + } +} diff --git a/src/main/webapp/WEB-INF/views/applicationmap.jsp b/src/main/webapp/WEB-INF/views/applicationmap.jsp index 12732399b..fb69babe7 100644 --- a/src/main/webapp/WEB-INF/views/applicationmap.jsp +++ b/src/main/webapp/WEB-INF/views/applicationmap.jsp @@ -32,6 +32,9 @@ "serviceTypeCode" : "${node.serviceType.code}", "terminal" : "${node.serviceType.terminal}", "isWas" : ${node.serviceType.was}, + + "histogram" : ${node.responseHistogramSummary.total.json}, + "serverList" : {