[유치수] [NOBTS] 서버맵에서 시간별 응답시간 차트 데이터 제공.

git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-web/trunk@2770 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
Chisu Yu
2013-11-05 05:37:10 +00:00
parent 66e00a06ba
commit 5bc7495fdb
10 changed files with 70 additions and 103 deletions
@@ -1,6 +1,5 @@
package com.nhn.pinpoint.web.applicationmap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
@@ -14,6 +14,7 @@ import com.nhn.pinpoint.web.applicationmap.rawdata.RawStatisticsData;
import com.nhn.pinpoint.web.applicationmap.rawdata.TransactionFlowStatistics;
import com.nhn.pinpoint.web.util.MergeableHashMap;
import com.nhn.pinpoint.web.util.MergeableMap;
import com.nhn.pinpoint.web.vo.TimeseriesResponses;
/**
* Application map
@@ -30,6 +31,8 @@ public class ApplicationMap {
private final MergeableMap<String, ApplicationRelation> relations = new MergeableHashMap<String, ApplicationRelation>();
private final Set<String> applicationNames = new HashSet<String>();
private TimeseriesResponses timeseriesResponse;
public ApplicationMap(Set<TransactionFlowStatistics> rawData) {
this.rawData = new RawStatisticsData(rawData);
logger.debug("ApplicationMap rawdata={}", this.rawData);
@@ -59,7 +62,7 @@ public class ApplicationMap {
}
}
// indexing application
// indexing application (UI의 서버맵을 그릴 때 key 정보가 필요한데 unique해야하고 link정보와 맞춰야 됨.)
indexingApplication();
// extract relation
@@ -126,4 +129,12 @@ public class ApplicationMap {
private void addRelation(ApplicationRelation relation) {
relations.putOrMerge(relation.getId(), relation);
}
public TimeseriesResponses getTimeseriesResponse() {
return timeseriesResponse;
}
public void setTimeseriesResponse(TimeseriesResponses timeseriesResponse) {
this.timeseriesResponse = timeseriesResponse;
}
}
@@ -1,6 +1,5 @@
package com.nhn.pinpoint.web.applicationmap.rawdata;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
@@ -8,6 +7,7 @@ import java.util.Set;
import com.nhn.pinpoint.common.ServiceType;
import com.nhn.pinpoint.common.bo.AgentInfoBo;
import com.nhn.pinpoint.web.util.Mergeable;
/**
* DB에서 조회한 application호출 관계 정보.
@@ -15,19 +15,34 @@ import com.nhn.pinpoint.common.bo.AgentInfoBo;
* @author netspider
*
*/
public class TransactionFlowStatistics {
public class TransactionFlowStatistics implements Mergeable<TransactionFlowStatistics> {
private String id;
private String from;
private ServiceType fromServiceType;
private String to;
private ServiceType toServiceType;
protected String id;
protected String from;
protected ServiceType fromServiceType;
protected String to;
protected ServiceType toServiceType;
// key = hostname
private Map<String, Host> toHostList;
/**
* key = hostname
*/
protected Map<String, Host> toHostList;
private Set<AgentInfoBo> toAgentSet;
protected Set<AgentInfoBo> toAgentSet;
public TransactionFlowStatistics(String from, short fromServiceType, String to, short toServiceType) {
this.from = from;
this.fromServiceType = ServiceType.findServiceType(fromServiceType);
this.to = to;
this.toServiceType = ServiceType.findServiceType(toServiceType);
this.toHostList = new HashMap<String, Host>();
this.id = TransactionFlowStatisticsUtils.makeId(this.from, this.fromServiceType, this.to, this.toServiceType);
}
public TransactionFlowStatistics(String from, ServiceType fromServiceType, String to, ServiceType toServiceType) {
this(from, fromServiceType.getCode(), to, toServiceType.getCode());
}
public String getFromApplicationId() {
return from + fromServiceType;
}
@@ -59,19 +74,6 @@ public class TransactionFlowStatistics {
}
}
public TransactionFlowStatistics(String from, short fromServiceType, String to, short toServiceType) {
this.from = from;
this.fromServiceType = ServiceType.findServiceType(fromServiceType);
this.to = to;
this.toServiceType = ServiceType.findServiceType(toServiceType);
this.toHostList = new HashMap<String, Host>();
this.id = TransactionFlowStatisticsUtils.makeId(this.from, this.fromServiceType, this.to, this.toServiceType);
}
public TransactionFlowStatistics(String from, ServiceType fromServiceType, String to, ServiceType toServiceType) {
this(from, fromServiceType.getCode(), to, toServiceType.getCode());
}
public void makeId() {
this.id = TransactionFlowStatisticsUtils.makeId(from, fromServiceType, to, toServiceType);
}
@@ -118,18 +120,10 @@ public class TransactionFlowStatistics {
public Map<String, Host> getToHostList() {
return toHostList;
// if (toHostList == null) {
// return null;
// }
// return Collections.unmodifiableMap(toHostList);
}
public Set<AgentInfoBo> getToAgentSet() {
return toAgentSet;
// if (toAgentSet == null) {
// return null;
// }
// return Collections.unmodifiableSet(toAgentSet);
}
public void addToAgentSet(Set<AgentInfoBo> agentSet) {
@@ -65,7 +65,7 @@ public class FilteredApplicationMapController {
LimitedScanResult<List<TransactionId>> limitedScanResult = filteredApplicationMapService.selectTraceIdsFromApplicationTraceIndex(applicationName, from, to, limit);
Filter filter = filterBuilder.build(filterText);
ApplicationMap map = filteredApplicationMapService.selectApplicationMap(limitedScanResult.getScanData(), /*from, to,*/ filter);
ApplicationMap map = filteredApplicationMapService.selectApplicationMap(limitedScanResult.getScanData(), from, to, filter);
model.addAttribute("from", from);
model.addAttribute("to", to);
@@ -79,7 +79,7 @@ public class FilteredApplicationMapController {
model.addAttribute("links", map.getLinks());
// FIXME linkstatistics detail에 보여주는 timeseries값을 서버맵에서 제공할 예정.
// model.addAttribute("timeseriesResponses", map.getTimeseriesResponses());
model.addAttribute("timeseriesResponses", map.getTimeseriesResponse());
return "applicationmap.filtered";
}
@@ -18,7 +18,7 @@ public interface FilteredApplicationMapService {
public LinkStatistics linkStatistics(long from, long to, List<TransactionId> traceIdSet, String srcApplicationName, short srcServiceType, String destApplicationName, short destServiceType, Filter filter);
public ApplicationMap selectApplicationMap(List<TransactionId> traceIdList, Filter filter);
public ApplicationMap selectApplicationMap(List<TransactionId> traceIdList, long from, long to, Filter filter);
public ApplicationMap selectApplicationMap(TransactionId transactionId);
}
@@ -30,6 +30,7 @@ import com.nhn.pinpoint.web.dao.TraceDao;
import com.nhn.pinpoint.web.filter.Filter;
import com.nhn.pinpoint.web.vo.LimitedScanResult;
import com.nhn.pinpoint.web.vo.LinkStatistics;
import com.nhn.pinpoint.web.vo.TimeseriesResponses;
import com.nhn.pinpoint.web.vo.TransactionId;
/**
@@ -119,14 +120,15 @@ public class FilteredApplicationMapServiceImpl implements FilteredApplicationMap
public ApplicationMap selectApplicationMap(TransactionId transactionId) {
List<TransactionId> transactionIdList = new ArrayList<TransactionId>();
transactionIdList.add(transactionId);
return selectApplicationMap(transactionIdList, Filter.NONE);
// FIXME from,to -1 땜방임.
return selectApplicationMap(transactionIdList, -1L, -1L, Filter.NONE);
}
/**
* filtered application map
*/
@Override
public ApplicationMap selectApplicationMap(List<TransactionId> transactionIdList, Filter filter) {
public ApplicationMap selectApplicationMap(List<TransactionId> transactionIdList, long from, long to, Filter filter) {
StopWatch watch = new StopWatch();
watch.start();
@@ -134,24 +136,23 @@ public class FilteredApplicationMapServiceImpl implements FilteredApplicationMap
// 향후 tree base로 충돌구간을 점검하여 없앨 경우 여기서 filter를 치면 안됨.
Collection<TransactionId> filterdList = recursiveCallFilter(transactionIdList);
// FIXME 나중에 List<Span>을 순회하면서 실행할 process chain을 두는것도 괜찮을듯.
List<List<SpanBo>> transactionList = this.traceDao.selectAllSpans(filterdList);
Set<TransactionFlowStatistics> statisticsData = new HashSet<TransactionFlowStatistics>();
Map<String, TransactionFlowStatistics> statisticsMap = new HashMap<String, TransactionFlowStatistics>();
Map<Long, SpanBo> transactionSpanMap = new HashMap<Long, SpanBo>();
// TimeseriesResponses tr = new TimeseriesResponses(from, to);
TimeseriesResponses tr = new TimeseriesResponses(from, to);
// System.out.println("@transactionList.size=" + transactionList.size() + "\n");
// 통계정보로 변환한다.
/**
* 통계정보로 변환한다.
*/
for (List<SpanBo> transaction : transactionList) {
if (!filter.include(transaction)) {
continue;
}
// System.out.println("@transaction.size=" + transaction.size() + "\n");
transactionSpanMap.clear();
for (SpanBo span : transaction) {
transactionSpanMap.put(span.getSpanId(), span);
@@ -186,44 +187,17 @@ public class FilteredApplicationMapServiceImpl implements FilteredApplicationMap
} else {
slot = destServiceType.getHistogram().findHistogramSlot(span.getElapsed()).getSlotTime();
}
// histogram.addSample((short) slot, 1);
//
// // host 정보 추가.
// stat.addToHost(span.getEndPoint());
//
// // agent 정보추가.
// String agentId = span.getAgentId();
// AgentInfoBo agentInfo = null;
// if (agentInfoCache.containsKey(agentId)) {
// agentInfo = agentInfoCache.get(agentId);
// } else {
// List<AgentInfoBo> agentInfoList = agentInfoDao.getAgentInfo(agentId, span.getAgentStartTime());
// if (!agentInfoList.isEmpty()) {
// agentInfo = agentInfoList.get(0);
// }
// agentInfoCache.put(agentId, agentInfo);
// }
// stat.addToAgent(agentInfo);
stat.addSample(dest, destServiceType.getCode(), (short) slot, 1);
statisticsData.add(stat);
statisticsMap.put(statId, stat);
// // link timeseries statistics추가.
// tr.add(statId, span.getCollectorAcceptTime(), span.getElapsed(), 1L);
// // application timeseries statistics
// tr.add(span.getApplicationId(), span.getCollectorAcceptTime(), span.getElapsed(), 1L);
// System.out.println("\n----------------------------------");
// System.out.println("@src\t\t" + src);
// System.out.println("@srcType\t\t" + srcServiceType);
// System.out.println("@dest\t\t" + dest);
// System.out.println("@destType\t" + destServiceType);
// System.out.println("@span\t\t" + span);
// System.out.println("@stat\t\t" + stat);
// System.out.println("----------------------------------\n\n");
// link timeseries statistics추가.
tr.add(statId, span.getCollectorAcceptTime(), span.getElapsed(), 1L);
// application timeseries statistics
tr.add(span.getApplicationId(), span.getCollectorAcceptTime(), span.getElapsed(), 1L);
/**
* span event의 statistics추가.
@@ -262,45 +236,31 @@ public class FilteredApplicationMapServiceImpl implements FilteredApplicationMap
} else {
slot2 = destServiceType.getHistogram().findHistogramSlot(spanEvent.getEndElapsed()).getSlotTime();
}
// histogram2.addSample((short) slot2, 1);
//
// // host 정보 추가.
// stat2.addToHost(spanEvent.getEndPoint());
// stat2.addSample((dest == null) ? spanEvent.getEndPoint() : dest, destServiceType.getCode(), (short) slot2, 1);
// FIXME
// stat2.addSample((dest == null) ? spanEvent.getEndPoint() : dest, destServiceType.getCode(), (short) slot2, 1);
stat2.addSample(spanEvent.getEndPoint(), destServiceType.getCode(), (short) slot2, 1);
// agent 정보추가. destination의 agent정보 알 수 없음.
statisticsData.add(stat2);
statisticsMap.put(statId2, stat2);
// // link timeseries statistics추가.
// tr.add(statId2, span.getStartTime() + spanEvent.getStartElapsed(), spanEvent.getEndElapsed(), 1L);
// link timeseries statistics추가.
tr.add(statId2, span.getStartTime() + spanEvent.getStartElapsed(), spanEvent.getEndElapsed(), 1L);
// // application timeseries statistics
// tr.add(spanEvent.getDestinationId(), span.getCollectorAcceptTime(), span.getElapsed(), 1L);
// System.out.println("\n\t----------------------------------");
// System.out.println("\t@src\t\t" + src);
// System.out.println("\t@srcType\t\t" + srcServiceType);
// System.out.println("\t@dest\t\t" + dest);
// System.out.println("\t@destType\t\t" + destServiceType);
// System.out.println("\t@spanEv\t\t" + spanEvent);
// System.out.println("\t@stat\t\t" + stat2);
// System.out.println("\t----------------------------------\n\n");
// application timeseries statistics
tr.add(spanEvent.getDestinationId(), span.getCollectorAcceptTime(), span.getElapsed(), 1L);
}
}
}
// mark agent info
for (TransactionFlowStatistics stat : statisticsData) {
fillAdditionalInfo(stat/* , from, to */);
fillAdditionalInfo(stat);
}
ApplicationMap map = new ApplicationMap(statisticsData).build();
// map.setTimeseriesResponses(tr);
map.setTimeseriesResponse(tr);
watch.stop();
logger.debug("Select filtered application map elapsed. {}ms", watch.getTotalTimeMillis());
@@ -27,7 +27,7 @@ public class TimeWindowUtils {
}
public static int getWindowIndex(long from, int windowSize, long timestamp) {
return (int) (timestamp - from) / windowSize;
return (int) (timestamp - from) / windowSize - 1;
}
public static int getWindowSize(long from, long to) {
@@ -97,12 +97,12 @@ public class LinkStatistics {
timeseriesValueList.add(makeEmptyTimeseriesValueMap());
}
public void addSample(long timestamp, int responseTimeslot, long callCount, boolean failed) {
logger.info("Add sample. timeslot=" + timestamp + ", responseTimeslot=" + responseTimeslot + ", callCount=" + callCount + ", failed=" + failed);
public void addSample(long timestamp, int responseTimeslot, long callCount, boolean isFailed) {
logger.info("Add sample. timeslot=" + timestamp + ", responseTimeslot=" + responseTimeslot + ", callCount=" + callCount + ", failed=" + isFailed);
timestamp = TimeWindowUtils.refineTimestamp(from, to, timestamp);
if (failed) {
if (isFailed) {
failedCount += callCount;
} else {
successCount += callCount;
@@ -76,6 +76,8 @@ public class TimeseriesResponses {
}
public void add(String id, long timestamp, int responseTime, long count) {
logger.debug("add sample id={}, timestamp={} responseTime={}, count={}", id, timestamp, responseTime, count);
List<Long> list = values.get(id);
if (list == null) {
@@ -77,5 +77,6 @@
} <c:if test="${!status.last}">,</c:if>
</c:forEach>
]
}
},
"timeseriesResponses" : ${timeseriesResponses.json}
}