From 4641a6e15986f2bb6946fe1438a2ff2ffa6cc73a Mon Sep 17 00:00:00 2001 From: Woonduk Kang Date: Thu, 18 Oct 2012 05:42:20 +0000 Subject: [PATCH] =?UTF-8?q?[=EA=B0=95=EC=9A=B4=EB=8D=95]=20[LUCYSUS-1744]?= =?UTF-8?q?=20hbase=20=EC=A0=80=EC=9E=A5=EC=8B=9C=EC=9D=98=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=EB=A5=BC=20=EC=BB=B4=ED=8C=A9=ED=8A=B8?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=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@808 84d0f5b1-2673-498c-a247-62c4ff18d310 --- .../hippo/web/calltree/rpc/RPCCallTree.java | 19 ++- .../hippo/web/calltree/rpc/RPCRequest.java | 6 + .../web/calltree/server/ServerCallTree.java | 17 ++- .../web/calltree/server/ServerRequest.java | 6 + .../hippo/web/calltree/span/SpanAlign.java | 7 +- .../hippo/web/calltree/span/SpanAligner.java | 51 +++---- .../web/controller/FlowChartController.java | 8 +- .../com/nhn/hippo/web/dao/HbaseTraceDao.java | 38 ++++- .../java/com/nhn/hippo/web/dao/TraceDao.java | 12 +- .../hippo/web/mapper/AnnotationMapper.java | 61 ++++++++ .../hippo/web/mapper/JavaObjectDecoder.java | 4 +- .../com/nhn/hippo/web/mapper/SpanMapper.java | 111 +++++++++++---- .../web/service/FlowChartServiceImpl.java | 16 ++- .../hippo/web/service/SpanServiceImpl.java | 7 +- .../nhn/hippo/web/vo/BusinessTransaction.java | 132 +++++++++--------- .../hippo/web/vo/BusinessTransactions.java | 55 ++++---- src/main/resources/log4j.xml | 5 +- src/main/resources/root-context.xml | 6 +- src/main/resources/servlet-context.xml | 12 +- .../hippo/web/service/SpanServiceTest.java | 28 ++-- .../resources/test-web-applicationContext.xml | 8 +- 21 files changed, 407 insertions(+), 202 deletions(-) create mode 100644 src/main/java/com/nhn/hippo/web/mapper/AnnotationMapper.java diff --git a/src/main/java/com/nhn/hippo/web/calltree/rpc/RPCCallTree.java b/src/main/java/com/nhn/hippo/web/calltree/rpc/RPCCallTree.java index b62e75f32..2d2c42de1 100644 --- a/src/main/java/com/nhn/hippo/web/calltree/rpc/RPCCallTree.java +++ b/src/main/java/com/nhn/hippo/web/calltree/rpc/RPCCallTree.java @@ -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 rpcs = new HashMap(); private final Map spanIdToRPCId = new HashMap(); private final Map requests = new HashMap(); - private final List spans = new ArrayList(); + private final List spans = new ArrayList(); 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(); diff --git a/src/main/java/com/nhn/hippo/web/calltree/rpc/RPCRequest.java b/src/main/java/com/nhn/hippo/web/calltree/rpc/RPCRequest.java index 742319dff..1c7e62a63 100644 --- a/src/main/java/com/nhn/hippo/web/calltree/rpc/RPCRequest.java +++ b/src/main/java/com/nhn/hippo/web/calltree/rpc/RPCRequest.java @@ -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(); diff --git a/src/main/java/com/nhn/hippo/web/calltree/server/ServerCallTree.java b/src/main/java/com/nhn/hippo/web/calltree/server/ServerCallTree.java index 29b53aa98..ef802e5b9 100644 --- a/src/main/java/com/nhn/hippo/web/calltree/server/ServerCallTree.java +++ b/src/main/java/com/nhn/hippo/web/calltree/server/ServerCallTree.java @@ -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 servers = new HashMap(); private final Map spanIdToServerId = new HashMap(); private final Map ServerRequests = new HashMap(); - private final List spans = new ArrayList(); + private final List spans = new ArrayList(); 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인 경우 보여주지 않음. diff --git a/src/main/java/com/nhn/hippo/web/calltree/server/ServerRequest.java b/src/main/java/com/nhn/hippo/web/calltree/server/ServerRequest.java index 09ec67dc3..af68cde19 100644 --- a/src/main/java/com/nhn/hippo/web/calltree/server/ServerRequest.java +++ b/src/main/java/com/nhn/hippo/web/calltree/server/ServerRequest.java @@ -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(); diff --git a/src/main/java/com/nhn/hippo/web/calltree/span/SpanAlign.java b/src/main/java/com/nhn/hippo/web/calltree/span/SpanAlign.java index dd1598373..287787553 100644 --- a/src/main/java/com/nhn/hippo/web/calltree/span/SpanAlign.java +++ b/src/main/java/com/nhn/hippo/web/calltree/span/SpanAlign.java @@ -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; } } diff --git a/src/main/java/com/nhn/hippo/web/calltree/span/SpanAligner.java b/src/main/java/com/nhn/hippo/web/calltree/span/SpanAligner.java index a1eab0327..f2209e318 100644 --- a/src/main/java/com/nhn/hippo/web/calltree/span/SpanAligner.java +++ b/src/main/java/com/nhn/hippo/web/calltree/span/SpanAligner.java @@ -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 spans; + private List spans; // private Map spanIdMap; - private Map> parentSpanIdMap; + private Map> parentSpanIdMap; private int depth = 0; - private static final Comparator timeComparator = new Comparator() { + private static final Comparator timeComparator = new Comparator() { @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 spans) { + public SpanAligner(List spans) { this.spans = spans; } @@ -46,28 +47,28 @@ public class SpanAligner { List result = new ArrayList(spans.size()); - Span root = findRoot(); + SpanBo root = findRoot(); logger.debug("find root {}", root); result.add(new SpanAlign(0, root)); - List next = nextSpan(root); + List next = nextSpan(root); doNext(next, result); return result; } public void buildIndex() { SpanIdChecker spanIdCheck = new SpanIdChecker(spans); - Map> parentSpanIdMap = new HashMap>(); + Map> parentSpanIdMap = new HashMap>(); - for (Span span : spans) { + for (SpanBo span : spans) { spanIdCheck.check(span); long parentSpanId = span.getParentSpanId(); - List spanList = parentSpanIdMap.get(parentSpanId); + List spanList = parentSpanIdMap.get(parentSpanId); if (spanList != null) { spanList.add(span); } else { - LinkedList newSpanList = new LinkedList(); + LinkedList newSpanList = new LinkedList(); newSpanList.add(span); parentSpanIdMap.put(parentSpanId, newSpanList); } @@ -77,20 +78,20 @@ public class SpanAligner { this.parentSpanIdMap = parentSpanIdMap; } - private void doNext(List spans, List result) { + private void doNext(List spans, List 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 nextSpan = nextSpan(next); + List nextSpan = nextSpan(next); doNext(nextSpan, result); } } finally { @@ -108,8 +109,8 @@ public class SpanAligner { } - private List nextSpan(Span parent) { - List child = this.parentSpanIdMap.get(parent.getSpanId()); + private List nextSpan(SpanBo parent) { + List child = this.parentSpanIdMap.get(parent.getSpanId()); if (child == null) { return null; } @@ -120,8 +121,8 @@ public class SpanAligner { } - private Span findRoot() { - List root = this.parentSpanIdMap.get(SPAN_ROOT); + private SpanBo findRoot() { + List 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 spanCheck = new HashMap(); - private List spans; + private Map spanCheck = new HashMap(); + private List spans; - public SpanIdChecker(List spans) { + public SpanIdChecker(List 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); diff --git a/src/main/java/com/nhn/hippo/web/controller/FlowChartController.java b/src/main/java/com/nhn/hippo/web/controller/FlowChartController.java index 8dc7eff89..526caf998 100644 --- a/src/main/java/com/nhn/hippo/web/controller/FlowChartController.java +++ b/src/main/java/com/nhn/hippo/web/controller/FlowChartController.java @@ -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"; } diff --git a/src/main/java/com/nhn/hippo/web/dao/HbaseTraceDao.java b/src/main/java/com/nhn/hippo/web/dao/HbaseTraceDao.java index ce58ddeab..a9d5953c0 100644 --- a/src/main/java/com/nhn/hippo/web/dao/HbaseTraceDao.java +++ b/src/main/java/com/nhn/hippo/web/dao/HbaseTraceDao.java @@ -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> spanMapper; + private RowMapper> spanMapper; + @Autowired + @Qualifier("spanAnnotationMapper") + private RowMapper> spanAnnotationMapper; @Override - public List selectSpan(UUID traceId) { + public List selectSpan(UUID traceId) { byte[] uuidBytes = BytesUtils.longLongToBytes(traceId.getMostSignificantBits(), traceId.getLeastSignificantBits()); return template2.get(HBaseTables.TRACES, uuidBytes, COLFAM_SPAN, spanMapper); } + public List 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 selectSpan(long traceIdMost, long traceIdLeast) { + public List selectSpan(long traceIdMost, long traceIdLeast) { byte[] uuidBytes = BytesUtils.longLongToBytes(traceIdMost, traceIdLeast); return template2.get(HBaseTables.TRACES, uuidBytes, COLFAM_SPAN, spanMapper); } @Override - public List> selectSpans(List traceIds) { + public List> selectSpans(List traceIds) { List gets = new ArrayList(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> selectSpans(Set traceIds) { + public List> selectSpans(Set traceIds) { List gets = new ArrayList(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> selectSpansAndAnnotation(Set traceIds) { + List gets = new ArrayList(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); + } } diff --git a/src/main/java/com/nhn/hippo/web/dao/TraceDao.java b/src/main/java/com/nhn/hippo/web/dao/TraceDao.java index d6263618b..469ee51c1 100644 --- a/src/main/java/com/nhn/hippo/web/dao/TraceDao.java +++ b/src/main/java/com/nhn/hippo/web/dao/TraceDao.java @@ -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 selectSpan(UUID traceId); + List selectSpan(UUID traceId); - List selectSpan(long traceIdMost, long traceIdLeast); + List selectSpanAndAnnotation(UUID traceId); - List> selectSpans(List traceIds); + List selectSpan(long traceIdMost, long traceIdLeast); - List> selectSpans(Set traceIds); + List> selectSpans(List traceIds); + List> selectSpans(Set traceIds); + + List> selectSpansAndAnnotation(Set traceIds); } diff --git a/src/main/java/com/nhn/hippo/web/mapper/AnnotationMapper.java b/src/main/java/com/nhn/hippo/web/mapper/AnnotationMapper.java new file mode 100644 index 000000000..e955bb50c --- /dev/null +++ b/src/main/java/com/nhn/hippo/web/mapper/AnnotationMapper.java @@ -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>> { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Override + public Map> mapRow(Result result, int rowNum) throws Exception { + KeyValue[] keyList = result.raw(); + Map> annotationList = new HashMap>(); + + 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 bos = new ArrayList(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; + } +} diff --git a/src/main/java/com/nhn/hippo/web/mapper/JavaObjectDecoder.java b/src/main/java/com/nhn/hippo/web/mapper/JavaObjectDecoder.java index ff1d711ca..5c81a1616 100644 --- a/src/main/java/com/nhn/hippo/web/mapper/JavaObjectDecoder.java +++ b/src/main/java/com/nhn/hippo/web/mapper/JavaObjectDecoder.java @@ -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(); diff --git a/src/main/java/com/nhn/hippo/web/mapper/SpanMapper.java b/src/main/java/com/nhn/hippo/web/mapper/SpanMapper.java index 0f994de00..4573d8466 100644 --- a/src/main/java/com/nhn/hippo/web/mapper/SpanMapper.java +++ b/src/main/java/com/nhn/hippo/web/mapper/SpanMapper.java @@ -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> { +public class SpanMapper implements RowMapper> { 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 mapRow(Result result, int rowNum) throws Exception { - NavigableMap familyMap = result.getFamilyMap(COLFAM_SPAN); - if (familyMap == null) { - return Collections.emptyList(); + public List 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 spanList = new ArrayList(); + 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> annotationMap = annotationMapper.mapRow(result, rowNum); + addAnnotation(spanList, annotationMap); } - List spanList = new ArrayList(familyMap.size()); - // TODO thrift 포멧이 아니고 따로 풀어서 넣어야 될거 같음. - TDeserializer de = new TDeserializer(); - for (NavigableMap.Entry 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 familyMap = result.getFamilyMap(COLFAM_SPAN); +// if (familyMap == null) { +// return Collections.emptyList(); +// } + +// List spanList = new ArrayList(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 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 spanList, Map> annotationMap) { + for (SpanBo bo : spanList) { + long spanID = bo.getSpanId(); + List anoList = annotationMap.get(spanID); + bo.setAnnotationBoList(anoList); + } } } diff --git a/src/main/java/com/nhn/hippo/web/service/FlowChartServiceImpl.java b/src/main/java/com/nhn/hippo/web/service/FlowChartServiceImpl.java index c9aef08b8..38c9ba568 100755 --- a/src/main/java/com/nhn/hippo/web/service/FlowChartServiceImpl.java +++ b/src/main/java/com/nhn/hippo/web/service/FlowChartServiceImpl.java @@ -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 bytes = this.traceIndexDao.scanTraceIndex(agentIds[0], from, to); // 이런 필터로직을 scan filter에서 할수 없나? Set result = new HashSet(); @@ -120,9 +124,9 @@ public class FlowChartServiceImpl implements FlowChartService { @Override public RPCCallTree selectRPCCallTree(Set traceIds) { final RPCCallTree tree = new RPCCallTree(); - List> traces = this.traceDao.selectSpans(traceIds); - for (List transaction : traces) { - for (Span eachTransaction : transaction) { + List> traces = this.traceDao.selectSpans(traceIds); + for (List transaction : traces) { + for (SpanBo eachTransaction : transaction) { tree.addSpan(eachTransaction); } } @@ -133,10 +137,10 @@ public class FlowChartServiceImpl implements FlowChartService { public ServerCallTree selectServerCallTree(Set traceIds) { final ServerCallTree tree = new ServerCallTree(); - List> traces = this.traceDao.selectSpans(traceIds); + List> traces = this.traceDao.selectSpansAndAnnotation(traceIds); - for (List transaction : traces) { - for (Span eachTransaction : transaction) { + for (List transaction : traces) { + for (SpanBo eachTransaction : transaction) { tree.addSpan(eachTransaction); } } diff --git a/src/main/java/com/nhn/hippo/web/service/SpanServiceImpl.java b/src/main/java/com/nhn/hippo/web/service/SpanServiceImpl.java index 015b7518f..1b316aab0 100644 --- a/src/main/java/com/nhn/hippo/web/service/SpanServiceImpl.java +++ b/src/main/java/com/nhn/hippo/web/service/SpanServiceImpl.java @@ -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 selectSpan(String uuid) { UUID id = UUID.fromString(uuid); - List spans = traceDao.selectSpan(id); - logger.debug("spans11 {}", spans); + List spans = traceDao.selectSpanAndAnnotation(id); if (spans == null) { return Collections.emptyList(); } @@ -42,7 +41,7 @@ public class SpanServiceImpl implements SpanService { } - private List order(List spans) { + private List order(List spans) { SpanAligner spanAligner = new SpanAligner(spans); return spanAligner.sort(); diff --git a/src/main/java/com/nhn/hippo/web/vo/BusinessTransaction.java b/src/main/java/com/nhn/hippo/web/vo/BusinessTransaction.java index 93fc767d6..cae656f3e 100644 --- a/src/main/java/com/nhn/hippo/web/vo/BusinessTransaction.java +++ b/src/main/java/com/nhn/hippo/web/vo/BusinessTransaction.java @@ -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 traces = new ArrayList(); - private final String name; + private final List traces = new ArrayList(); + 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 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 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 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 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 getTraces() { - return traces; - } + public List 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; + } } diff --git a/src/main/java/com/nhn/hippo/web/vo/BusinessTransactions.java b/src/main/java/com/nhn/hippo/web/vo/BusinessTransactions.java index 18e3d958b..8752e0543 100644 --- a/src/main/java/com/nhn/hippo/web/vo/BusinessTransactions.java +++ b/src/main/java/com/nhn/hippo/web/vo/BusinessTransactions.java @@ -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 { - private final Map transactions = new HashMap(); - private Iterator> iterator; + private final Map transactions = new HashMap(); + private Iterator> 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 iterator() { - iterator = transactions.entrySet().iterator(); + @Override + public Iterator iterator() { + iterator = transactions.entrySet().iterator(); - return new Iterator() { - @Override - public boolean hasNext() { - return iterator.hasNext(); - } + return new Iterator() { + @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() { - } - }; - } + } + }; + } } diff --git a/src/main/resources/log4j.xml b/src/main/resources/log4j.xml index fe20c132c..e092cdeb5 100644 --- a/src/main/resources/log4j.xml +++ b/src/main/resources/log4j.xml @@ -4,7 +4,8 @@ - + + @@ -23,7 +24,7 @@ - + diff --git a/src/main/resources/root-context.xml b/src/main/resources/root-context.xml index 8dc1bbb52..aac5a2941 100644 --- a/src/main/resources/root-context.xml +++ b/src/main/resources/root-context.xml @@ -16,5 +16,9 @@ - + + + + + diff --git a/src/main/resources/servlet-context.xml b/src/main/resources/servlet-context.xml index 3a7679c0d..cd402c7ec 100644 --- a/src/main/resources/servlet-context.xml +++ b/src/main/resources/servlet-context.xml @@ -32,11 +32,11 @@ - - - - + + + + - - + + \ No newline at end of file diff --git a/src/test/java/com/nhn/hippo/web/service/SpanServiceTest.java b/src/test/java/com/nhn/hippo/web/service/SpanServiceTest.java index 63035ea9d..4174fc90e 100644 --- a/src/test/java/com/nhn/hippo/web/service/SpanServiceTest.java +++ b/src/test/java/com/nhn/hippo/web/service/SpanServiceTest.java @@ -2,15 +2,13 @@ package com.nhn.hippo.web.service; import com.nhn.hippo.web.calltree.span.SpanAlign; import com.profiler.common.dto.thrift.Annotation; -import com.profiler.common.dto.thrift.BinaryAnnotation; import com.profiler.common.dto.thrift.Span; import com.profiler.common.hbase.HBaseTables; import com.profiler.common.hbase.HbaseTemplate2; import com.profiler.common.util.SpanUtils; -import com.profiler.server.dao.Traces; +import com.profiler.server.dao.TraceDao; import org.apache.hadoop.hbase.client.Delete; import org.apache.thrift.TException; -import org.apache.thrift.TSerializer; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -20,10 +18,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.UUID; +import java.util.*; import java.util.concurrent.atomic.AtomicInteger; /** @@ -35,7 +30,7 @@ public class SpanServiceTest { @Autowired - private Traces traces; + private TraceDao traceDao; @Autowired private SpanService spanService; @@ -82,7 +77,7 @@ public class SpanServiceTest { public void after() { List list = new LinkedList(); for (Span span : deleteSpans) { - Delete delete = new Delete(SpanUtils.getTracesRowkey(span)); + Delete delete = new Delete(SpanUtils.getTraceId(span)); list.add(delete); } template2.delete(HBaseTables.TRACES, list); @@ -94,6 +89,11 @@ public class SpanServiceTest { doRead(root); } + @Test + public void testReadSpanAndAnnotation() throws TException { + doRead(root); + } + private void doRead(Span span) { UUID uuid = new UUID(span.getMostTraceId(), span.getLeastTraceId()); @@ -107,9 +107,7 @@ public class SpanServiceTest { private void insert(Span span) throws TException { - TSerializer se = new TSerializer(); - byte[] serialize = se.serialize(span); - traces.insert(span, serialize); + traceDao.insert(span); } AtomicInteger id = new AtomicInteger(0); @@ -122,6 +120,9 @@ public class SpanServiceTest { int andIncrement = id.getAndIncrement(); Span span = new Span("UnitTest", time, uuid.getMostSignificantBits(), uuid.getLeastSignificantBits(), "test", "rpc" + andIncrement, andIncrement, ano, "protocol:ip:port", false); span.setParentSpanId(-1); + List annotations = new ArrayList(); + annotations.add(new Annotation(0, "root ann", 0)); + span.setAnnotations(annotations); return span; } @@ -131,6 +132,9 @@ public class SpanServiceTest { int andIncrement = id.getAndIncrement(); Span sub = new Span("UnitTest", time, span.getMostTraceId(), span.getLeastTraceId(), "test", "rpc" + andIncrement, andIncrement, ano, "protocol:ip:port", false); sub.setParentSpanId(span.getSpanId()); + List annotations = new ArrayList(); + annotations.add(new Annotation(0, "sub ann" + andIncrement, 0)); + sub.setAnnotations(annotations); return sub; } diff --git a/src/test/resources/test-web-applicationContext.xml b/src/test/resources/test-web-applicationContext.xml index d612dcd74..54b688f49 100644 --- a/src/test/resources/test-web-applicationContext.xml +++ b/src/test/resources/test-web-applicationContext.xml @@ -28,11 +28,15 @@ - + - + + + + + \ No newline at end of file