mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-27 21:56:38 +10:00
[강운덕] [LUCYSUS-1744] hbase 저장시의 데이터를 컴팩트하게 함.
git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-web/trunk@808 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
@@ -7,7 +7,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Call Tree
|
||||
@@ -16,16 +18,18 @@ import com.profiler.common.dto.thrift.Span;
|
||||
*/
|
||||
public class RPCCallTree {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
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, RPCRequest> requests = new HashMap<String, RPCRequest>();
|
||||
private final List<Span> spans = new ArrayList<Span>();
|
||||
private final List<SpanBo> spans = new ArrayList<SpanBo>();
|
||||
|
||||
private boolean isBuilt = false;
|
||||
|
||||
public void addSpan(Span span) {
|
||||
public void addSpan(SpanBo span) {
|
||||
/**
|
||||
* make RPCs
|
||||
*/
|
||||
@@ -64,7 +68,7 @@ public class RPCCallTree {
|
||||
entry.getValue().setSequence(i++);
|
||||
}
|
||||
|
||||
for (Span span : spans) {
|
||||
for (SpanBo span : spans) {
|
||||
String from = String.valueOf(span.getParentSpanId());
|
||||
String to = String.valueOf(span.getSpanId());
|
||||
|
||||
@@ -74,7 +78,12 @@ public class RPCCallTree {
|
||||
if (fromRPC == null) {
|
||||
fromRPC = rpcs.get(spanIdToRPCId.get(PREFIX_CLIENT + to));
|
||||
}
|
||||
|
||||
// TODO 없는 url에 대한 호출이 고려되어야 함. 일단 임시로 회피.
|
||||
if (fromRPC == null) {
|
||||
logger.debug("invalid fromrpc {}", from);
|
||||
continue;
|
||||
}
|
||||
logger.debug("form:{}, to:{}", fromRPC, to);
|
||||
RPCRequest request = new RPCRequest(fromRPC, toRPC);
|
||||
if (requests.containsKey(request.getId())) {
|
||||
requests.get(request.getId()).increaseCallCount();
|
||||
|
||||
@@ -10,6 +10,12 @@ public class RPCRequest {
|
||||
private int callCount = 1;
|
||||
|
||||
public RPCRequest(RPC from, RPC to) {
|
||||
if (from == null) {
|
||||
throw new NullPointerException("form must not be null");
|
||||
}
|
||||
if (to == null) {
|
||||
throw new NullPointerException("to must not be null");
|
||||
}
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.id = from.getId() + to.getId();
|
||||
|
||||
@@ -8,7 +8,9 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.nhn.hippo.web.vo.BusinessTransactions;
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Call Tree
|
||||
@@ -17,17 +19,19 @@ import com.profiler.common.dto.thrift.Span;
|
||||
*/
|
||||
public class ServerCallTree {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private final String PREFIX_CLIENT = "CLIENT:";
|
||||
|
||||
private final Map<String, Server> servers = new HashMap<String, Server>();
|
||||
private final Map<String, String> spanIdToServerId = new HashMap<String, String>();
|
||||
private final Map<String, ServerRequest> ServerRequests = new HashMap<String, ServerRequest>();
|
||||
private final List<Span> spans = new ArrayList<Span>();
|
||||
private final List<SpanBo> spans = new ArrayList<SpanBo>();
|
||||
private final BusinessTransactions businessTransactions = new BusinessTransactions();
|
||||
|
||||
private boolean isBuilt = false;
|
||||
|
||||
public void addSpan(Span span) {
|
||||
public void addSpan(SpanBo span) {
|
||||
/**
|
||||
* make Servers
|
||||
*/
|
||||
@@ -70,7 +74,7 @@ public class ServerCallTree {
|
||||
entry.getValue().setSequence(i++);
|
||||
}
|
||||
|
||||
for (Span span : spans) {
|
||||
for (SpanBo span : spans) {
|
||||
String from = String.valueOf(span.getParentSpanId());
|
||||
String to = String.valueOf(span.getSpanId());
|
||||
|
||||
@@ -81,6 +85,11 @@ public class ServerCallTree {
|
||||
fromServer = servers.get(spanIdToServerId.get(PREFIX_CLIENT + to));
|
||||
}
|
||||
|
||||
// TODO 없는 url에 대한 호출이 고려되어야 함. 일단 임시로 회피.
|
||||
if (fromServer == null) {
|
||||
logger.debug("invalid form server {}", from);
|
||||
continue;
|
||||
}
|
||||
ServerRequest serverRequest = new ServerRequest(fromServer, toServer);
|
||||
|
||||
// TODO: local call인 경우 보여주지 않음.
|
||||
|
||||
@@ -10,6 +10,12 @@ public class ServerRequest {
|
||||
private int callCount = 1;
|
||||
|
||||
public ServerRequest(Server from, Server to) {
|
||||
if (from == null) {
|
||||
throw new NullPointerException("from must not be null");
|
||||
}
|
||||
if (to == null) {
|
||||
throw new NullPointerException("to must not be null");
|
||||
}
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.id = from.getId() + to.getId();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.nhn.hippo.web.calltree.span;
|
||||
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
@@ -8,9 +9,9 @@ import org.apache.commons.lang.StringUtils;
|
||||
*/
|
||||
public class SpanAlign {
|
||||
private int depth;
|
||||
private Span span;
|
||||
private SpanBo span;
|
||||
|
||||
public SpanAlign(int depth, Span span) {
|
||||
public SpanAlign(int depth, SpanBo span) {
|
||||
this.depth = depth;
|
||||
this.span = span;
|
||||
}
|
||||
@@ -27,7 +28,7 @@ public class SpanAlign {
|
||||
// return sb.toString();
|
||||
// }
|
||||
|
||||
public Span getSpan() {
|
||||
public SpanBo getSpan() {
|
||||
return span;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.nhn.hippo.web.calltree.span;
|
||||
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -13,18 +14,18 @@ public class SpanAligner {
|
||||
|
||||
public static final Long SPAN_ROOT = -1L;
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
private List<Span> spans;
|
||||
private List<SpanBo> spans;
|
||||
|
||||
// private Map<Long, Span> spanIdMap;
|
||||
private Map<Long, List<Span>> parentSpanIdMap;
|
||||
private Map<Long, List<SpanBo>> parentSpanIdMap;
|
||||
|
||||
private int depth = 0;
|
||||
|
||||
private static final Comparator<Span> timeComparator = new Comparator<Span>() {
|
||||
private static final Comparator<SpanBo> timeComparator = new Comparator<SpanBo>() {
|
||||
@Override
|
||||
public int compare(Span o1, Span o2) {
|
||||
public int compare(SpanBo o1, SpanBo o2) {
|
||||
long o1Timestamp = o1.getTimestamp();
|
||||
long o2Timestamp = o2.getTimestamp();
|
||||
if (o1Timestamp > o2Timestamp) {
|
||||
@@ -37,7 +38,7 @@ public class SpanAligner {
|
||||
}
|
||||
};
|
||||
|
||||
public SpanAligner(List<Span> spans) {
|
||||
public SpanAligner(List<SpanBo> spans) {
|
||||
this.spans = spans;
|
||||
}
|
||||
|
||||
@@ -46,28 +47,28 @@ public class SpanAligner {
|
||||
|
||||
List<SpanAlign> result = new ArrayList<SpanAlign>(spans.size());
|
||||
|
||||
Span root = findRoot();
|
||||
SpanBo root = findRoot();
|
||||
logger.debug("find root {}", root);
|
||||
result.add(new SpanAlign(0, root));
|
||||
|
||||
List<Span> next = nextSpan(root);
|
||||
List<SpanBo> next = nextSpan(root);
|
||||
doNext(next, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void buildIndex() {
|
||||
SpanIdChecker spanIdCheck = new SpanIdChecker(spans);
|
||||
Map<Long, List<Span>> parentSpanIdMap = new HashMap<Long, List<Span>>();
|
||||
Map<Long, List<SpanBo>> parentSpanIdMap = new HashMap<Long, List<SpanBo>>();
|
||||
|
||||
for (Span span : spans) {
|
||||
for (SpanBo span : spans) {
|
||||
spanIdCheck.check(span);
|
||||
|
||||
long parentSpanId = span.getParentSpanId();
|
||||
List<Span> spanList = parentSpanIdMap.get(parentSpanId);
|
||||
List<SpanBo> spanList = parentSpanIdMap.get(parentSpanId);
|
||||
if (spanList != null) {
|
||||
spanList.add(span);
|
||||
} else {
|
||||
LinkedList<Span> newSpanList = new LinkedList<Span>();
|
||||
LinkedList<SpanBo> newSpanList = new LinkedList<SpanBo>();
|
||||
newSpanList.add(span);
|
||||
parentSpanIdMap.put(parentSpanId, newSpanList);
|
||||
}
|
||||
@@ -77,20 +78,20 @@ public class SpanAligner {
|
||||
this.parentSpanIdMap = parentSpanIdMap;
|
||||
}
|
||||
|
||||
private void doNext(List<Span> spans, List<SpanAlign> result) {
|
||||
private void doNext(List<SpanBo> spans, List<SpanAlign> result) {
|
||||
if (spans == null) {
|
||||
return;
|
||||
}
|
||||
depth++;
|
||||
try {
|
||||
for (Span next : spans) {
|
||||
for (SpanBo next : spans) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("{} {} next {}", new Object[]{getSpace(), depth, next});
|
||||
}
|
||||
|
||||
result.add(new SpanAlign(depth, next));
|
||||
|
||||
List<Span> nextSpan = nextSpan(next);
|
||||
List<SpanBo> nextSpan = nextSpan(next);
|
||||
doNext(nextSpan, result);
|
||||
}
|
||||
} finally {
|
||||
@@ -108,8 +109,8 @@ public class SpanAligner {
|
||||
}
|
||||
|
||||
|
||||
private List<Span> nextSpan(Span parent) {
|
||||
List<Span> child = this.parentSpanIdMap.get(parent.getSpanId());
|
||||
private List<SpanBo> nextSpan(SpanBo parent) {
|
||||
List<SpanBo> child = this.parentSpanIdMap.get(parent.getSpanId());
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -120,8 +121,8 @@ public class SpanAligner {
|
||||
}
|
||||
|
||||
|
||||
private Span findRoot() {
|
||||
List<Span> root = this.parentSpanIdMap.get(SPAN_ROOT);
|
||||
private SpanBo findRoot() {
|
||||
List<SpanBo> root = this.parentSpanIdMap.get(SPAN_ROOT);
|
||||
if (root == null) {
|
||||
logger.warn("root span not found. {}", spans);
|
||||
throw new IllegalStateException("root span not found");
|
||||
@@ -134,15 +135,15 @@ public class SpanAligner {
|
||||
}
|
||||
|
||||
public static class SpanIdChecker {
|
||||
private Map<Long, Span> spanCheck = new HashMap<Long, Span>();
|
||||
private List<Span> spans;
|
||||
private Map<Long, SpanBo> spanCheck = new HashMap<Long, SpanBo>();
|
||||
private List<SpanBo> spans;
|
||||
|
||||
public SpanIdChecker(List<Span> spans) {
|
||||
public SpanIdChecker(List<SpanBo> spans) {
|
||||
this.spans = spans;
|
||||
}
|
||||
|
||||
public void check(Span span) {
|
||||
Span before = spanCheck.put(span.getSpanId(), span);
|
||||
public void check(SpanBo span) {
|
||||
SpanBo before = spanCheck.put(span.getSpanId(), span);
|
||||
if (before != null) {
|
||||
// span id 중복체크
|
||||
deplicatedSpanIdDump(span);
|
||||
@@ -150,7 +151,7 @@ public class SpanAligner {
|
||||
}
|
||||
}
|
||||
|
||||
private void deplicatedSpanIdDump(Span span) {
|
||||
private void deplicatedSpanIdDump(SpanBo span) {
|
||||
// 중복 span dump
|
||||
Logger internalLog = LoggerFactory.getLogger(this.getClass());
|
||||
internalLog.info("duplicated spanId {}, list:{}", span, spans);
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.nhn.hippo.web.controller;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
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;
|
||||
@@ -22,6 +24,8 @@ import com.nhn.hippo.web.vo.TraceId;
|
||||
@Controller
|
||||
public class FlowChartController {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
private FlowChartService flow;
|
||||
|
||||
@@ -35,7 +39,7 @@ public class FlowChartController {
|
||||
model.addAttribute("nodes", callTree.getNodes());
|
||||
model.addAttribute("links", callTree.getLinks());
|
||||
|
||||
System.out.println(callTree.toString());
|
||||
logger.debug("callTree:{}", callTree);
|
||||
|
||||
return "flow";
|
||||
}
|
||||
@@ -51,7 +55,7 @@ public class FlowChartController {
|
||||
model.addAttribute("links", callTree.getLinks());
|
||||
model.addAttribute("businessTransactions", callTree.getBusinessTransactions().iterator());
|
||||
|
||||
System.out.println(callTree.toString());
|
||||
logger.debug("callTree:{}", callTree);
|
||||
|
||||
return "flowserver";
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.nhn.hippo.web.dao;
|
||||
|
||||
import com.nhn.hippo.web.vo.TraceId;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
import com.profiler.common.hbase.HBaseTables;
|
||||
import com.profiler.common.hbase.HbaseOperations2;
|
||||
@@ -25,7 +26,10 @@ import java.util.UUID;
|
||||
@Repository
|
||||
public class HbaseTraceDao implements TraceDao {
|
||||
|
||||
private final byte[] COLFAM_SPAN = Bytes.toBytes("Span");
|
||||
private final byte[] COLFAM_SPAN = HBaseTables.TRACES_CF_SPAN;
|
||||
|
||||
private final byte[] COLFAM_ANNOTATION = HBaseTables.TRACES_CF_ANNOTATION;
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Autowired
|
||||
@@ -33,23 +37,34 @@ public class HbaseTraceDao implements TraceDao {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("spanMapper")
|
||||
private RowMapper<List<Span>> spanMapper;
|
||||
private RowMapper<List<SpanBo>> spanMapper;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("spanAnnotationMapper")
|
||||
private RowMapper<List<SpanBo>> spanAnnotationMapper;
|
||||
|
||||
@Override
|
||||
public List<Span> selectSpan(UUID traceId) {
|
||||
public List<SpanBo> selectSpan(UUID traceId) {
|
||||
byte[] uuidBytes = BytesUtils.longLongToBytes(traceId.getMostSignificantBits(), traceId.getLeastSignificantBits());
|
||||
return template2.get(HBaseTables.TRACES, uuidBytes, COLFAM_SPAN, spanMapper);
|
||||
}
|
||||
|
||||
public List<SpanBo> selectSpanAndAnnotation(UUID traceId) {
|
||||
byte[] uuidBytes = BytesUtils.longLongToBytes(traceId.getMostSignificantBits(), traceId.getLeastSignificantBits());
|
||||
Get get = new Get(uuidBytes);
|
||||
get.addFamily(COLFAM_SPAN);
|
||||
get.addFamily(COLFAM_ANNOTATION);
|
||||
return template2.get(HBaseTables.TRACES, get, spanAnnotationMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Span> selectSpan(long traceIdMost, long traceIdLeast) {
|
||||
public List<SpanBo> selectSpan(long traceIdMost, long traceIdLeast) {
|
||||
byte[] uuidBytes = BytesUtils.longLongToBytes(traceIdMost, traceIdLeast);
|
||||
return template2.get(HBaseTables.TRACES, uuidBytes, COLFAM_SPAN, spanMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<Span>> selectSpans(List<UUID> traceIds) {
|
||||
public List<List<SpanBo>> selectSpans(List<UUID> traceIds) {
|
||||
List<Get> gets = new ArrayList<Get>(traceIds.size());
|
||||
for (UUID traceId : traceIds) {
|
||||
byte[] uuidBytes = BytesUtils.longLongToBytes(traceId.getMostSignificantBits(), traceId.getLeastSignificantBits());
|
||||
@@ -61,7 +76,7 @@ public class HbaseTraceDao implements TraceDao {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<Span>> selectSpans(Set<TraceId> traceIds) {
|
||||
public List<List<SpanBo>> selectSpans(Set<TraceId> traceIds) {
|
||||
List<Get> gets = new ArrayList<Get>(traceIds.size());
|
||||
for (TraceId traceId : traceIds) {
|
||||
Get get = new Get(traceId.getBytes());
|
||||
@@ -70,4 +85,15 @@ public class HbaseTraceDao implements TraceDao {
|
||||
}
|
||||
return template2.get(HBaseTables.TRACES, gets, spanMapper);
|
||||
}
|
||||
|
||||
public List<List<SpanBo>> selectSpansAndAnnotation(Set<TraceId> traceIds) {
|
||||
List<Get> gets = new ArrayList<Get>(traceIds.size());
|
||||
for (TraceId traceId : traceIds) {
|
||||
Get get = new Get(traceId.getBytes());
|
||||
get.addFamily(COLFAM_SPAN);
|
||||
get.addFamily(COLFAM_ANNOTATION);
|
||||
gets.add(get);
|
||||
}
|
||||
return template2.get(HBaseTables.TRACES, gets, spanAnnotationMapper);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.nhn.hippo.web.dao;
|
||||
|
||||
|
||||
import com.nhn.hippo.web.vo.TraceId;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
|
||||
import java.util.List;
|
||||
@@ -13,12 +14,15 @@ import java.util.UUID;
|
||||
*/
|
||||
public interface TraceDao {
|
||||
|
||||
List<Span> selectSpan(UUID traceId);
|
||||
List<SpanBo> selectSpan(UUID traceId);
|
||||
|
||||
List<Span> selectSpan(long traceIdMost, long traceIdLeast);
|
||||
List<SpanBo> selectSpanAndAnnotation(UUID traceId);
|
||||
|
||||
List<List<Span>> selectSpans(List<UUID> traceIds);
|
||||
List<SpanBo> selectSpan(long traceIdMost, long traceIdLeast);
|
||||
|
||||
List<List<Span>> selectSpans(Set<TraceId> traceIds);
|
||||
List<List<SpanBo>> selectSpans(List<UUID> traceIds);
|
||||
|
||||
List<List<SpanBo>> selectSpans(Set<TraceId> traceIds);
|
||||
|
||||
List<List<SpanBo>> selectSpansAndAnnotation(Set<TraceId> traceIds);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.nhn.hippo.web.mapper;
|
||||
|
||||
import com.profiler.common.bo.AnnotationBo;
|
||||
import com.profiler.common.hbase.HBaseTables;
|
||||
import com.profiler.common.util.BytesUtils;
|
||||
import org.apache.hadoop.hbase.KeyValue;
|
||||
import org.apache.hadoop.hbase.client.Result;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.hadoop.hbase.RowMapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class AnnotationMapper implements RowMapper<Map<Long, List<AnnotationBo>>> {
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
@Override
|
||||
public Map<Long, List<AnnotationBo>> mapRow(Result result, int rowNum) throws Exception {
|
||||
KeyValue[] keyList = result.raw();
|
||||
Map<Long, List<AnnotationBo>> annotationList = new HashMap<Long, List<AnnotationBo>>();
|
||||
|
||||
for (KeyValue kv : keyList) {
|
||||
byte[] buffer = kv.getBuffer();
|
||||
long spanId = BytesUtils.bytesToLong(buffer, kv.getQualifierOffset());
|
||||
|
||||
int offset = kv.getValueOffset();
|
||||
if (kv.getFamilyLength() == HBaseTables.TRACES_CF_ANNOTATION.length) {
|
||||
// byte[] value = kv.getValue();
|
||||
// if(value == null) {
|
||||
// continue;
|
||||
// }
|
||||
int valueLength = kv.getValueLength();
|
||||
if (valueLength == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int size = BytesUtils.bytesToInt(buffer, offset);
|
||||
if (size == 0) {
|
||||
continue;
|
||||
}
|
||||
offset += 4;
|
||||
List<AnnotationBo> bos = new ArrayList<AnnotationBo>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
AnnotationBo annotationBo = new AnnotationBo();
|
||||
annotationBo.setSpanId(spanId);
|
||||
offset = annotationBo.readValue(buffer, offset);
|
||||
bos.add(annotationBo);
|
||||
logger.trace("read annotation:{}", annotationBo);
|
||||
}
|
||||
annotationList.put(spanId, bos);
|
||||
}
|
||||
}
|
||||
return annotationList;
|
||||
}
|
||||
}
|
||||
@@ -33,8 +33,8 @@ public class JavaObjectDecoder implements BinaryAnnotationDecoder {
|
||||
// ByteArrayInputStream ins = new ByteArrayInputStream(binaryAnnotation.getValue());
|
||||
// try {
|
||||
// ObjectInputStream in = new ObjectInputStream(ins);
|
||||
// Object readObject = in.readObject();
|
||||
// return readObject;
|
||||
// Object readValue = in.readValue();
|
||||
// return readValue;
|
||||
// } catch (IOException e) {
|
||||
// logger.warn("binaryAnnotation decode fail Cause:{}", e.getMessage(), e);
|
||||
// return "binaryAnnotation decode fail Cause:" + e.getMessage();
|
||||
|
||||
@@ -1,53 +1,112 @@
|
||||
package com.nhn.hippo.web.mapper;
|
||||
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
import com.profiler.common.bo.AnnotationBo;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import com.profiler.common.hbase.HBaseTables;
|
||||
import com.profiler.common.util.BytesUtils;
|
||||
import org.apache.hadoop.hbase.KeyValue;
|
||||
import org.apache.hadoop.hbase.client.Result;
|
||||
import org.apache.hadoop.hbase.util.Bytes;
|
||||
import org.apache.thrift.TDeserializer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.hadoop.hbase.RowMapper;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class SpanMapper implements RowMapper<List<Span>> {
|
||||
public class SpanMapper implements RowMapper<List<SpanBo>> {
|
||||
|
||||
private final byte[] COLFAM_SPAN = Bytes.toBytes("Span");
|
||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
// private BinaryAnnotationDecoder binaryAnnotationDecoder = new JavaObjectDecoder();
|
||||
private AnnotationMapper annotationMapper;
|
||||
|
||||
public AnnotationMapper getAnnotationMapper() {
|
||||
return annotationMapper;
|
||||
}
|
||||
|
||||
public void setAnnotationMapper(AnnotationMapper annotationMapper) {
|
||||
this.annotationMapper = annotationMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Span> mapRow(Result result, int rowNum) throws Exception {
|
||||
NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(COLFAM_SPAN);
|
||||
if (familyMap == null) {
|
||||
return Collections.emptyList();
|
||||
public List<SpanBo> mapRow(Result result, int rowNum) throws Exception {
|
||||
byte[] rowKey = result.getRow();
|
||||
long most = BytesUtils.bytesToFirstLong(rowKey);
|
||||
long least = BytesUtils.bytesToSecondLong(rowKey);
|
||||
|
||||
KeyValue[] keyList = result.raw();
|
||||
List<SpanBo> spanList = new ArrayList<SpanBo>();
|
||||
for (KeyValue kv : keyList) {
|
||||
// family name "span"일때로만 한정.
|
||||
if (kv.getFamilyLength() == HBaseTables.TRACES_CF_SPAN.length) {
|
||||
SpanBo spanBo = new SpanBo();
|
||||
spanBo.setMostTraceId(most);
|
||||
spanBo.setLeastTraceId(least);
|
||||
|
||||
spanBo.setSpanID(Bytes.toLong(kv.getBuffer(), kv.getQualifierOffset()));
|
||||
spanBo.setSpanID(Bytes.toLong(kv.getQualifier()));
|
||||
spanBo.setTimestamp(kv.getTimestamp());
|
||||
spanBo.readValue(kv.getBuffer(), kv.getValueOffset());
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("read span :{}", spanBo);
|
||||
}
|
||||
spanList.add(spanBo);
|
||||
}
|
||||
}
|
||||
if (annotationMapper != null) {
|
||||
Map<Long, List<AnnotationBo>> annotationMap = annotationMapper.mapRow(result, rowNum);
|
||||
addAnnotation(spanList, annotationMap);
|
||||
}
|
||||
|
||||
List<Span> spanList = new ArrayList<Span>(familyMap.size());
|
||||
// TODO thrift 포멧이 아니고 따로 풀어서 넣어야 될거 같음.
|
||||
TDeserializer de = new TDeserializer();
|
||||
for (NavigableMap.Entry<byte[], byte[]> entry : familyMap.entrySet()) {
|
||||
Span span = new Span();
|
||||
// spainid가 이미 value에 들어 있어서 일단 필요가 없음.
|
||||
//byte[] spanId = entry.getKey();
|
||||
de.deserialize(span, entry.getValue());
|
||||
// if (binaryAnnotationDecoder != null) {
|
||||
// binaryAnnotationDecoder.decode(span);
|
||||
// }
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("deserailze span :{}", span);
|
||||
}
|
||||
spanList.add(span);
|
||||
}
|
||||
|
||||
return spanList;
|
||||
|
||||
// NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(COLFAM_SPAN);
|
||||
// if (familyMap == null) {
|
||||
// return Collections.emptyList();
|
||||
// }
|
||||
|
||||
// List<SpanBo> spanList = new ArrayList<SpanBo>(familyMap.size());
|
||||
// Put put = new Put(SpanUtils.getTracesRowkey(span), span.getTimestamp());
|
||||
// // TODO columName이 중복일 경우를 확인가능하면 span id 중복 발급을 알수 있음.
|
||||
// put.add(COLFAM_SPAN, Bytes.toBytes(span.getSpanID()), value);
|
||||
|
||||
// byte[] rowKey = result.getRow();
|
||||
// long most = BytesUtils.bytesToFirstLong(rowKey);
|
||||
// long least = BytesUtils.bytesToSecondLong(rowKey);
|
||||
//
|
||||
// for (NavigableMap.Entry<byte[], byte[]> entry : familyMap.entrySet()) {
|
||||
// SpanBo spanBo = new SpanBo();
|
||||
//
|
||||
// spanBo.setMostTraceID(most);
|
||||
// spanBo.setLeastTraceID(least);
|
||||
// spanBo.setSpanID(Bytes.toLong(entry.getKey()));
|
||||
// //
|
||||
// //byte[] spanId = entry.getKey();
|
||||
//// if (binaryAnnotationDecoder != null) {
|
||||
//// binaryAnnotationDecoder.decode(span);
|
||||
//// }
|
||||
//
|
||||
// if (logger.isDebugEnabled()) {
|
||||
// logger.debug("read span :{}", spanBo);
|
||||
// }
|
||||
// spanList.add(spanBo);
|
||||
// }
|
||||
// return spanList;
|
||||
}
|
||||
|
||||
private void addAnnotation(List<SpanBo> spanList, Map<Long, List<AnnotationBo>> annotationMap) {
|
||||
for (SpanBo bo : spanList) {
|
||||
long spanID = bo.getSpanId();
|
||||
List<AnnotationBo> anoList = annotationMap.get(spanID);
|
||||
bo.setAnnotationBoList(anoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.nhn.hippo.web.dao.TraceDao;
|
||||
import com.nhn.hippo.web.dao.TraceIndexDao;
|
||||
import com.nhn.hippo.web.service.TracesProcessor.SpanHandler;
|
||||
import com.nhn.hippo.web.vo.TraceId;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
import com.profiler.common.hbase.HBaseClient;
|
||||
import com.profiler.common.hbase.HBaseQuery;
|
||||
@@ -67,6 +68,9 @@ public class FlowChartServiceImpl implements FlowChartService {
|
||||
|
||||
if (agentIds.length == 1) {
|
||||
// single scan
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("scan {}, {}, {}", new Object[]{agentIds[0], from, to});
|
||||
}
|
||||
List<byte[]> bytes = this.traceIndexDao.scanTraceIndex(agentIds[0], from, to);
|
||||
// 이런 필터로직을 scan filter에서 할수 없나?
|
||||
Set<TraceId> result = new HashSet<TraceId>();
|
||||
@@ -120,9 +124,9 @@ public class FlowChartServiceImpl implements FlowChartService {
|
||||
@Override
|
||||
public RPCCallTree selectRPCCallTree(Set<TraceId> traceIds) {
|
||||
final RPCCallTree tree = new RPCCallTree();
|
||||
List<List<Span>> traces = this.traceDao.selectSpans(traceIds);
|
||||
for (List<Span> transaction : traces) {
|
||||
for (Span eachTransaction : transaction) {
|
||||
List<List<SpanBo>> traces = this.traceDao.selectSpans(traceIds);
|
||||
for (List<SpanBo> transaction : traces) {
|
||||
for (SpanBo eachTransaction : transaction) {
|
||||
tree.addSpan(eachTransaction);
|
||||
}
|
||||
}
|
||||
@@ -133,10 +137,10 @@ public class FlowChartServiceImpl implements FlowChartService {
|
||||
public ServerCallTree selectServerCallTree(Set<TraceId> traceIds) {
|
||||
final ServerCallTree tree = new ServerCallTree();
|
||||
|
||||
List<List<Span>> traces = this.traceDao.selectSpans(traceIds);
|
||||
List<List<SpanBo>> traces = this.traceDao.selectSpansAndAnnotation(traceIds);
|
||||
|
||||
for (List<Span> transaction : traces) {
|
||||
for (Span eachTransaction : transaction) {
|
||||
for (List<SpanBo> transaction : traces) {
|
||||
for (SpanBo eachTransaction : transaction) {
|
||||
tree.addSpan(eachTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.nhn.hippo.web.service;
|
||||
import com.nhn.hippo.web.calltree.span.SpanAlign;
|
||||
import com.nhn.hippo.web.calltree.span.SpanAligner;
|
||||
import com.nhn.hippo.web.dao.TraceDao;
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -27,8 +27,7 @@ public class SpanServiceImpl implements SpanService {
|
||||
@Override
|
||||
public List<SpanAlign> selectSpan(String uuid) {
|
||||
UUID id = UUID.fromString(uuid);
|
||||
List<Span> spans = traceDao.selectSpan(id);
|
||||
logger.debug("spans11 {}", spans);
|
||||
List<SpanBo> spans = traceDao.selectSpanAndAnnotation(id);
|
||||
if (spans == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
@@ -42,7 +41,7 @@ public class SpanServiceImpl implements SpanService {
|
||||
|
||||
}
|
||||
|
||||
private List<SpanAlign> order(List<Span> spans) {
|
||||
private List<SpanAlign> order(List<SpanBo> spans) {
|
||||
|
||||
SpanAligner spanAligner = new SpanAligner(spans);
|
||||
return spanAligner.sort();
|
||||
|
||||
@@ -4,84 +4,86 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.profiler.common.bo.AnnotationBo;
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import com.profiler.common.dto.thrift.Annotation;
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
|
||||
public class BusinessTransaction {
|
||||
private final List<String> traces = new ArrayList<String>();
|
||||
private final String name;
|
||||
private final List<String> traces = new ArrayList<String>();
|
||||
private final String name;
|
||||
|
||||
private int calls = 0;
|
||||
private long totalTime = 0;
|
||||
private long maxTime = 0;
|
||||
private long minTime = 0;
|
||||
private int calls = 0;
|
||||
private long totalTime = 0;
|
||||
private long maxTime = 0;
|
||||
private long minTime = 0;
|
||||
|
||||
public BusinessTransaction(Span span) {
|
||||
this.name = span.getName();
|
||||
this.traces.add(new UUID(span.getMostTraceId(), span.getLeastTraceId()).toString());
|
||||
calls++;
|
||||
public BusinessTransaction(SpanBo span) {
|
||||
this.name = span.getName();
|
||||
this.traces.add(new UUID(span.getMostTraceId(), span.getLeastTraceId()).toString());
|
||||
calls++;
|
||||
|
||||
List<Annotation> annotations = span.getAnnotations();
|
||||
long begin = 0;
|
||||
long end = 0;
|
||||
for (Annotation a : annotations) {
|
||||
if (a.getKey().equals("SR") || a.getKey().equals("CS")) {
|
||||
begin = a.getTimestamp();
|
||||
}
|
||||
if (a.getKey().equals("SS") || a.getKey().equals("CR")) {
|
||||
end = a.getTimestamp();
|
||||
}
|
||||
}
|
||||
long elapsed = end - begin;
|
||||
totalTime = maxTime = minTime = elapsed;
|
||||
}
|
||||
List<AnnotationBo> annotations = span.getAnnotationBoList();
|
||||
long begin = 0;
|
||||
long end = 0;
|
||||
for (AnnotationBo a : annotations) {
|
||||
if (a.getKey().equals("SR") || a.getKey().equals("CS")) {
|
||||
begin = a.getTimestamp();
|
||||
}
|
||||
if (a.getKey().equals("SS") || a.getKey().equals("CR")) {
|
||||
end = a.getTimestamp();
|
||||
}
|
||||
}
|
||||
long elapsed = end - begin;
|
||||
totalTime = maxTime = minTime = elapsed;
|
||||
}
|
||||
|
||||
public void add(Span span) {
|
||||
this.traces.add(new UUID(span.getMostTraceId(), span.getLeastTraceId()).toString());
|
||||
if (span.getParentSpanId() == -1) {
|
||||
calls++;
|
||||
}
|
||||
public void add(SpanBo span) {
|
||||
this.traces.add(new UUID(span.getMostTraceId(), span.getLeastTraceId()).toString());
|
||||
if (span.getParentSpanId() == -1) {
|
||||
calls++;
|
||||
}
|
||||
|
||||
List<Annotation> annotations = span.getAnnotations();
|
||||
long begin = 0;
|
||||
long end = 0;
|
||||
for (Annotation a : annotations) {
|
||||
if (a.getKey().equals("SR") || a.getKey().equals("CS")) {
|
||||
begin = a.getTimestamp();
|
||||
}
|
||||
if (a.getKey().equals("SS") || a.getKey().equals("CR")) {
|
||||
end = a.getTimestamp();
|
||||
}
|
||||
}
|
||||
long elapsed = end - begin;
|
||||
totalTime += elapsed;
|
||||
if (maxTime < elapsed)
|
||||
maxTime = elapsed;
|
||||
if (minTime > elapsed)
|
||||
minTime = elapsed;
|
||||
}
|
||||
List<AnnotationBo> annotations = span.getAnnotationBoList();
|
||||
long begin = 0;
|
||||
long end = 0;
|
||||
for (AnnotationBo a : annotations) {
|
||||
if (a.getKey().equals("SR") || a.getKey().equals("CS")) {
|
||||
begin = a.getTimestamp();
|
||||
}
|
||||
if (a.getKey().equals("SS") || a.getKey().equals("CR")) {
|
||||
end = a.getTimestamp();
|
||||
}
|
||||
}
|
||||
long elapsed = end - begin;
|
||||
totalTime += elapsed;
|
||||
if (maxTime < elapsed)
|
||||
maxTime = elapsed;
|
||||
if (minTime > elapsed)
|
||||
minTime = elapsed;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<String> getTraces() {
|
||||
return traces;
|
||||
}
|
||||
public List<String> getTraces() {
|
||||
return traces;
|
||||
}
|
||||
|
||||
public int getCalls() {
|
||||
return calls;
|
||||
}
|
||||
public int getCalls() {
|
||||
return calls;
|
||||
}
|
||||
|
||||
public long getTotalTime() {
|
||||
return totalTime;
|
||||
}
|
||||
public long getTotalTime() {
|
||||
return totalTime;
|
||||
}
|
||||
|
||||
public long getMaxTime() {
|
||||
return maxTime;
|
||||
}
|
||||
public long getMaxTime() {
|
||||
return maxTime;
|
||||
}
|
||||
|
||||
public long getMinTime() {
|
||||
return minTime;
|
||||
}
|
||||
public long getMinTime() {
|
||||
return minTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,41 +5,42 @@ import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.profiler.common.bo.SpanBo;
|
||||
import com.profiler.common.dto.thrift.Span;
|
||||
|
||||
public final class BusinessTransactions implements Iterable<BusinessTransaction> {
|
||||
|
||||
private final Map<String, BusinessTransaction> transactions = new HashMap<String, BusinessTransaction>();
|
||||
private Iterator<Entry<String, BusinessTransaction>> iterator;
|
||||
private final Map<String, BusinessTransaction> transactions = new HashMap<String, BusinessTransaction>();
|
||||
private Iterator<Entry<String, BusinessTransaction>> iterator;
|
||||
|
||||
public void add(Span span) {
|
||||
String name = span.getName();
|
||||
if (transactions.containsKey(name)) {
|
||||
transactions.get(name).add(span);
|
||||
} else {
|
||||
transactions.put(name, new BusinessTransaction(span));
|
||||
}
|
||||
}
|
||||
public void add(SpanBo span) {
|
||||
String name = span.getName();
|
||||
if (transactions.containsKey(name)) {
|
||||
transactions.get(name).add(span);
|
||||
} else {
|
||||
transactions.put(name, new BusinessTransaction(span));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BusinessTransaction> iterator() {
|
||||
iterator = transactions.entrySet().iterator();
|
||||
@Override
|
||||
public Iterator<BusinessTransaction> iterator() {
|
||||
iterator = transactions.entrySet().iterator();
|
||||
|
||||
return new Iterator<BusinessTransaction>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
return new Iterator<BusinessTransaction>() {
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BusinessTransaction next() {
|
||||
return iterator.next().getValue();
|
||||
}
|
||||
@Override
|
||||
public BusinessTransaction next() {
|
||||
return iterator.next().getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
@Override
|
||||
public void remove() {
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user