[유치수] [NOBTS] add calltree

git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-web/trunk@708 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
Chisu Yu
2012-09-26 08:26:33 +00:00
parent c6f8d9b243
commit b588ec1fbb
16 changed files with 385 additions and 118 deletions
@@ -0,0 +1,55 @@
package com.nhn.hippo.web.calltree;
/**
*
* @author netspider
*
*/
public class RPC implements Comparable<RPC> {
private int sequence;
private final String id;
private final String agentId;
private final String serviceName;
private final String rpc;
public RPC(String agentId, String serviceName, String rpc) {
this.id = agentId + ":" + serviceName + ":" + rpc;
this.agentId = agentId;
this.serviceName = serviceName;
this.rpc = rpc;
}
public String getId() {
return this.id;
}
public void setSequence(int sequence) {
this.sequence = sequence;
}
public int getSequence() {
return sequence;
}
public String getAgentId() {
return agentId;
}
public String getServiceName() {
return serviceName;
}
public String getRpc() {
return rpc;
}
@Override
public int compareTo(RPC rpc) {
return id.compareTo(rpc.id);
}
@Override
public String toString() {
return id + ", seq=" + sequence;
}
}
@@ -0,0 +1,104 @@
package com.nhn.hippo.web.calltree;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.profiler.common.dto.thrift.Span;
/**
* Call Tree
*
* @author netspider
*
*/
public class RPCCallTree {
private final String PREFIX_CLIENT = "CLIENT:";
private final Map<String, RPC> rpcs = new HashMap<String, RPC>();
private final Map<String, String> spanIdToRPCId = new HashMap<String, String>();
private final Map<String, Request> requests = new HashMap<String, Request>();
private final List<Span> spans = new ArrayList<Span>();
private boolean isBuilt = false;
public void addSpan(Span span) {
System.out.println("Add span to calltree=" + span + "\n");
/**
* make RPCs
*/
// TODO: 여기에서 이러지말고 수집할 때 처음부터 table에 저장해둘 수 있나??
RPC rpc = new RPC(span.getAgentID(), span.getServiceName(), span.getName());
if (!rpcs.containsKey(rpc.getId())) {
rpcs.put(rpc.getId(), rpc);
}
spanIdToRPCId.put(String.valueOf(span.getSpanID()), rpc.getId());
if (span.getParentSpanId() == -1) {
RPC client = new RPC(PREFIX_CLIENT + span.getAgentID(), span.getServiceName(), span.getName());
rpcs.put(client.getId(), client);
spanIdToRPCId.put(PREFIX_CLIENT + span.getSpanID(), client.getId());
}
/**
* Preparing makes link (requests)
*/
spans.add(span);
}
public RPCCallTree build() {
if (isBuilt)
return this;
int i = 0;
for (Entry<String, RPC> entry : rpcs.entrySet()) {
entry.getValue().setSequence(i++);
}
for (Span span : spans) {
String from = String.valueOf(span.getParentSpanId());
String to = String.valueOf(span.getSpanID());
RPC fromRPC = rpcs.get(spanIdToRPCId.get(from));
RPC toRPC = rpcs.get(spanIdToRPCId.get(to));
if (fromRPC == null) {
fromRPC = rpcs.get(spanIdToRPCId.get(PREFIX_CLIENT + to));
}
Request request = new Request(fromRPC, toRPC);
if (requests.containsKey(request.getId())) {
requests.get(request.getId()).increaseCallCount();
} else {
requests.put(request.getId(), request);
}
}
isBuilt = true;
return this;
}
public Collection<RPC> getNodes() {
return this.rpcs.values();
}
public Collection<Request> getLinks() {
return this.requests.values();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("RPCS=").append(rpcs);
sb.append("\n");
sb.append("REQUESTS=").append(requests.values());
return sb.toString();
}
}
@@ -0,0 +1,46 @@
package com.nhn.hippo.web.calltree;
/**
*
* @author netspider
*
*/
public class Request {
private final String id;
private final RPC from;
private final RPC to;
private int callCount = 1;
public Request(RPC from, RPC to) {
this.from = from;
this.to = to;
this.id = from.getId() + to.getId();
}
public void increaseCallCount() {
callCount++;
}
public String getId() {
return id;
}
public RPC getFrom() {
return from;
}
public RPC getTo() {
return to;
}
public int getCallCount() {
return callCount;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{from=").append(from).append(", to=").append(to).append(", cc=").append(callCount).append("}");
return sb.toString();
}
}
@@ -10,8 +10,15 @@ 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.calltree.RPCCallTree;
import com.nhn.hippo.web.service.FlowChartService;
/**
* retrieve data for drawing call tree.
*
* @author netspider
*
*/
@Controller
public class FlowChartController {
@@ -20,8 +27,7 @@ public class FlowChartController {
/**
* <pre>
* testurl = http://localhost:7080/flow.hippo?host=TEST_AGENT_ID&from=1348453800000&to=1348453900000
* testurl = http://localhost:7080/flow.hippo?host=TEST_AGENT_ID&from=0&to=1348493900000
* testurl = netscurl "http://localhost:7080/flow.hippo?host=TEST_AGENT_ID&from=1348565386677&to=1348565386677"
* </pre>
*
* @param model
@@ -36,18 +42,22 @@ public class FlowChartController {
* get agentId list from 'Servers'
*/
String[] selectAgentIds = flow.selectAgentIds(hosts);
System.out.println("selectedAgentIds=" + Arrays.toString(selectAgentIds));
/**
* get traceId list from 'TraceIndex'
*/
List<byte[]> iterator = flow.selectTraceIdsFromTraceIndex(hosts, from, to);
List<byte[]> traceIds = flow.selectTraceIdsFromTraceIndex(hosts, from, to);
/**
* get all traces from 'Trace'
* get call tree
*/
flow.selectTraces(iterator);
RPCCallTree callTree = flow.selectCallTree(traceIds);
model.addAttribute("nodes", callTree.getNodes());
model.addAttribute("links", callTree.getLinks());
model.addAttribute("value", "hello world");
System.out.println(callTree.toString());
return "flow";
}
@@ -2,15 +2,48 @@ package com.nhn.hippo.web.service;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import com.nhn.hippo.web.calltree.RPCCallTree;
import com.profiler.common.dto.thrift.Span;
/**
*
* @author netspider
*
*/
public interface FlowChartService {
/**
* select agentIds from Server table
*
* @param hosts
* @return
*/
public String[] selectAgentIds(String[] hosts);
/**
* select traceIds from TraceIndex table
*
* @param agentIds
* @param from
* @param to
* @return
*/
public List<byte[]> selectTraceIdsFromTraceIndex(String[] agentIds, long from, long to);
/**
* select Traces from Trace table
*
* @param traceIds
* @return
*/
public Map<byte[], List<Span>> selectTraces(List<byte[]> traceIds);
/**
* select call tree
*
* @param traceIds
* @return
*/
public RPCCallTree selectCallTree(List<byte[]> traceIds);
}
@@ -18,6 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import com.nhn.hippo.web.calltree.RPCCallTree;
import com.profiler.common.dto.thrift.Span;
import com.profiler.common.hbase.HBaseClient;
import com.profiler.common.hbase.HBaseQuery;
@@ -99,20 +100,17 @@ public class FlowChartServiceImpl implements FlowChartService {
TDeserializer deserializer = new TDeserializer();
/**
* Map<FAMILY, Map<COLUMN_NAME, Map<Timestamp, VALUE>>>
*/
NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> map = res.getMap();
for (Entry<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> entry : map.entrySet()) {
byte[] family = entry.getKey();
System.out.println("family=" + Bytes.toString(family));
// byte[] family = entry.getKey();
// System.out.println("family=" + Bytes.toString(family));
NavigableMap<byte[], NavigableMap<Long, byte[]>> values = entry.getValue();
for (Entry<byte[], NavigableMap<Long, byte[]>> value : values.entrySet()) {
byte[] colname = value.getKey();
System.out.println("colname=" + Bytes.toString(colname));
// byte[] colname = value.getKey();
// System.out.println("colname=" + Bytes.toString(colname));
NavigableMap<Long, byte[]> valueSeries = value.getValue();
@@ -131,4 +129,15 @@ public class FlowChartServiceImpl implements FlowChartService {
return list;
}
@Override
public RPCCallTree selectCallTree(List<byte[]> traceIds) {
List<Get> gets = new ArrayList<Get>(traceIds.size());
for (byte[] traceId : traceIds) {
gets.add(new Get(traceId));
}
Result[] results = client.get(HBaseTables.TRACES, gets);
return TracesProcessor.process(results);
}
}
@@ -0,0 +1,54 @@
package com.nhn.hippo.web.service;
import java.util.Map.Entry;
import java.util.NavigableMap;
import org.apache.hadoop.hbase.client.Result;
import org.apache.thrift.TDeserializer;
import org.apache.thrift.TException;
import com.nhn.hippo.web.calltree.RPCCallTree;
import com.profiler.common.dto.thrift.Span;
public class TracesProcessor {
public static RPCCallTree process(Result[] results) {
RPCCallTree callTree = new RPCCallTree();
TDeserializer deserializer = new TDeserializer();
for (Result res : results) {
/**
* res.getMap() represent
* "Map<FAMILY, Map<COLUMN_NAME, Map<Timestamp, VALUE>>>"
*/
NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> map = res.getMap();
for (Entry<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> entry : map.entrySet()) {
NavigableMap<byte[], NavigableMap<Long, byte[]>> values = entry.getValue();
/**
* For each column (SpanID)
*/
for (Entry<byte[], NavigableMap<Long, byte[]>> value : values.entrySet()) {
NavigableMap<Long, byte[]> valueSeries = value.getValue();
/**
* Decode span object
*/
for (Entry<Long, byte[]> v : valueSeries.entrySet()) {
Span span = new Span();
try {
deserializer.deserialize(span, v.getValue());
callTree.addSpan(span);
} catch (TException e) {
e.printStackTrace();
}
}
}
}
}
return callTree.build();
}
}
@@ -0,0 +1,11 @@
package com.nhn.hippo.web.timeline;
/**
* Trace Timeline
*
* @author netspider
*
*/
public class Timeline {
}