完成匿名URL查询链路调试信息展现功能。

This commit is contained in:
tanzhen 2015-11-19 19:16:54 +08:00
parent 0060a132e4
commit fc2d5f18ad
16 changed files with 755 additions and 393 deletions

View File

@ -3,14 +3,25 @@
*/
package com.ai.cloud.controller;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import com.ai.cloud.service.inter.IQueryTraceLogSer;
import com.ai.cloud.util.Constants;
import com.ai.cloud.vo.mvo.BuriedPointEntry;
import freemarker.template.SimpleSequence;
/**
* 首面请求处理
@ -21,7 +32,10 @@ import com.ai.cloud.util.Constants;
*/
@Controller
public class HelloSkyWalkingUICtl {
@Autowired
IQueryTraceLogSer traceLogSer;
private static Logger logger = LogManager.getLogger(HelloSkyWalkingUICtl.class);
/***
@ -75,9 +89,40 @@ public class HelloSkyWalkingUICtl {
* @return
* @throws Exception
*/
@RequestMapping(value = "/showTraceLog")
public String showTraceLog(ModelMap root) throws Exception {
this.showIndexPage(root, null);
@RequestMapping(value = "/showTraceLog/{traceId}")
public String showTraceLog(ModelMap root, @PathVariable("traceId") String traceId) throws Exception {
// traceId = "bcb759bc12db474aa54bc4bea605cb81123";
Map<String, BuriedPointEntry> traceLogMap = traceLogSer.queryLogByTraceId(traceId);
if (traceLogMap != null && traceLogMap.size() > 0) {
List<BuriedPointEntry> valueList = new ArrayList<BuriedPointEntry>();
valueList.addAll(traceLogMap.values());
final List<Long> endTime = new ArrayList<Long>();
endTime.add(0, 0l);
Collections.sort(valueList, new Comparator<BuriedPointEntry>() {
@Override
public int compare(BuriedPointEntry arg0, BuriedPointEntry arg1) {
/** 顺道取出日志最大的结束时间 */
if (endTime.get(0) < arg0.getEndDate()) {
endTime.set(0, arg0.getEndDate());
}
if (endTime.get(0) < arg1.getEndDate()) {
endTime.set(0, arg1.getEndDate());
}
return arg0.getColId().compareTo(arg1.getColId());
}
});
// int m = 1;
// for (BuriedPointEntry tmpEntry : valueList) {
// logger.info("sort result level:{} : {}", m++, tmpEntry);
// }
long beginTime = valueList.get(0).getStartDate();
root.put("valueList", valueList);
root.put("spanTypeMap", Constants.SPAN_TYPE_MAP);
root.put("statusCodeMap", Constants.STATUS_CODE_MAP);
root.put("beginTime", beginTime);
root.put("endTime", endTime.get(0));
}
return "traceLog";
}

View File

@ -0,0 +1,91 @@
/**
*
*/
package com.ai.cloud.dao.impl;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Repository;
import com.ai.cloud.dao.inter.IBuriedPointSDAO;
import com.ai.cloud.util.Constants;
import com.ai.cloud.util.HBaseConnectionUtil;
import com.ai.cloud.util.common.SortUtil;
import com.ai.cloud.vo.mvo.BuriedPointEntry;
import com.sun.tools.internal.ws.wsdl.framework.Entity;
/**
*
* @author tz
* @date 2015年11月18日 下午3:21:26
* @version V0.1
*/
@Repository
public class BuriedPointSDAO implements IBuriedPointSDAO {
private static Logger logger = LogManager.getLogger(BuriedPointSDAO.class);
/***
* 查询指定traceId的调用链日志
*
* @param tableName
* @param traceId
* @return
* @throws IOException
*/
public Map<String, BuriedPointEntry> queryLogByTraceId(String tableName, String traceId) throws IOException {
Table table = HBaseConnectionUtil.getConnection().getTable(TableName.valueOf(tableName));
Get g = new Get(Bytes.toBytes(traceId));
Result r = table.get(g);
Map<String, BuriedPointEntry> traceLogMap = new HashMap<String, BuriedPointEntry>();
Map<String, BuriedPointEntry> rpcMap = new HashMap<String, BuriedPointEntry>();
for (Cell cell : r.rawCells()) {
if (cell.getValueArray().length > 0) {
String colId = Bytes.toString(cell.getQualifierArray(), cell.getQualifierOffset(),
cell.getQualifierLength());
BuriedPointEntry tmpEntry = BuriedPointEntry.convert(
Bytes.toString(cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()), colId);
System.out.println("=========" + tmpEntry);
// 特殊处理RPC的服务端信息
if (colId.endsWith(Constants.RPC_END_FLAG)) {
rpcMap.put(colId.substring(0, colId.lastIndexOf(Constants.RPC_END_FLAG)), tmpEntry);
} else {
SortUtil.addCurNodeTreeMapKey(traceLogMap, colId, tmpEntry);
}
}
}
computeRPCInfo(rpcMap, traceLogMap);
//合并处理RPC日志信息
return traceLogMap;
}
/***
* 合并处理RPC日志信息
* @param rpcMap
* @param traceLogMap
*/
private void computeRPCInfo(Map<String, BuriedPointEntry> rpcMap, Map<String, BuriedPointEntry> traceLogMap) {
// 合并处理
if (rpcMap.size() > 0) {
for (Entry<String, BuriedPointEntry> rpcVO : rpcMap.entrySet()) {
String colId = rpcVO.getKey();
if(traceLogMap.containsKey(colId)){
BuriedPointEntry logVO = traceLogMap.get(colId);
logVO.addTimeLine(rpcVO.getValue().getStartDate(), rpcVO.getValue().getCost());
}
}
}
}
}

View File

@ -0,0 +1,21 @@
/**
*
*/
package com.ai.cloud.dao.inter;
import java.io.IOException;
import java.util.Map;
import com.ai.cloud.vo.mvo.BuriedPointEntry;
/**
*
* @author tz
* @date 2015年11月18日 下午3:21:49
* @version V0.1
*/
public interface IBuriedPointSDAO {
public Map<String, BuriedPointEntry> queryLogByTraceId(String tableName, String traceId) throws IOException;
}

View File

@ -0,0 +1,34 @@
/**
*
*/
package com.ai.cloud.service.impl;
import java.io.IOException;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ai.cloud.dao.inter.IBuriedPointSDAO;
import com.ai.cloud.service.inter.IQueryTraceLogSer;
import com.ai.cloud.util.Constants;
import com.ai.cloud.vo.mvo.BuriedPointEntry;
/**
*
* @author tz
* @date 2015年11月18日 下午5:57:11
* @version V0.1
*/
@Service
public class QueryTraceLogSerImpl implements IQueryTraceLogSer {
@Autowired
IBuriedPointSDAO buriedPointSDAO;
@Override
public Map<String, BuriedPointEntry> queryLogByTraceId(String traceId) throws IOException {
return buriedPointSDAO.queryLogByTraceId(Constants.TABLE_NAME_CHAIN, traceId);
}
}

View File

@ -0,0 +1,21 @@
/**
*
*/
package com.ai.cloud.service.inter;
import java.io.IOException;
import java.util.Map;
import com.ai.cloud.vo.mvo.BuriedPointEntry;
/**
*
* @author tz
* @date 2015年11月18日 下午5:56:04
* @version V0.1
*/
public interface IQueryTraceLogSer {
public Map<String, BuriedPointEntry> queryLogByTraceId(String traceId) throws IOException;
}

View File

@ -3,6 +3,9 @@
*/
package com.ai.cloud.util;
import java.util.HashMap;
import java.util.Map;
/**
* 常量类
* @author tz
@ -15,10 +18,40 @@ public class Constants {
public static final String VERSION_VAL = "0.1";
/** hbase集群*/
public static final String QUORUM = "10.1.235.197,10.1.235.198,10.1.235.199";
/** zk端口*/
public static final String CLIENT_PORT = "29181";
/** hbase表名*/
public static final String TABLE_NAME_CHAIN = "sw-call-chain";
/**层级分割符*/
public static final char VAL_SPLIT_CHAR = '.';
/** RPC远端调用节点结束标识*/
public static final String RPC_END_FLAG = "-S";
public static final String SPAN_TYPE_M = "M";
public static final String SPAN_TYPE_J = "J";
public static final String SPAN_TYPE_W = "W";
public static final String SPAN_TYPE_D = "D";
/** SPAN_TYPE码表*/
public static Map<String,String> SPAN_TYPE_MAP = new HashMap<String,String>(){{
put("M", "JAVA");
put("J", "JDBC");
put("W", "WEB SERVLET");
put("D", "DUBBO/DUBBOX");
}};
public static final char STATUS_CODE_0 = '0';
public static final char STATUS_CODE_1 = '1';
public static final char STATUS_CODE_9 = '9';
/** STATUS_CODE码表*/
public static Map<String,String> STATUS_CODE_MAP = new HashMap<String,String>(){{
put("0", "OK");
put("1", "FAIL");
put("9", "MISSING");
}};
}

View File

@ -3,25 +3,13 @@
*/
package com.ai.cloud.util;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.ai.cloud.vo.mvo.BuriedPointEntry;
/**
*
* @author tz
@ -35,7 +23,7 @@ public class HBaseConnectionUtil {
private static Configuration configuration = null;
private static Connection connection = null;
static {
public synchronized static Connection getConnection(){
try {
if (configuration == null) {
configuration = HBaseConfiguration.create();
@ -46,29 +34,6 @@ public class HBaseConnectionUtil {
} catch (Exception e) {
logger.error("Create table[{}] failed", "connection hbase fail", e);
}
}
public static List<BuriedPointEntry> selectByTraceId(String traceId) throws IOException {
List<BuriedPointEntry> entries = new ArrayList<BuriedPointEntry>();
Table table = connection.getTable(TableName.valueOf(Constants.TABLE_NAME_CHAIN));
Get g = new Get(Bytes.toBytes(traceId));
Result r = table.get(g);
for (Cell cell : r.listCells()) {
if (cell.getValueArray().length > 0)
entries.add(BuriedPointEntry.convert(new String(cell.getValue(), "UTF-8")));
}
return entries;
}
/**
* @throws IOException
*
*/
public static void main(String[] args) throws IOException {
List<BuriedPointEntry> bpe = HBaseConnectionUtil.selectByTraceId("08388950294948ef91e30e70c4ec183e123");
for (BuriedPointEntry tmpVO : bpe) {
logger.info(tmpVO);
}
return connection;
}
}

View File

@ -0,0 +1,187 @@
/**
*
*/
package com.ai.cloud.util.common;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.Test;
import com.ai.cloud.dao.impl.BuriedPointSDAO;
import com.ai.cloud.util.Constants;
import com.ai.cloud.vo.mvo.BuriedPointEntry;
/**
*
* @author tz
* @date 2015年11月18日 下午2:03:10
* @version V0.1
*/
public class SortUtil {
private static Logger logger = LogManager.getLogger(SortUtil.class);
/***
* 增加调度链路节点信息
*
* @param reMap
* @param colId
* @param tmpEntry
*/
public static void addCurNodeTreeMapKey(Map<String, BuriedPointEntry> reMap, String colId,
BuriedPointEntry tmpEntry) {
reMap.put(colId, tmpEntry);
// 根据当前Id查找上级如果不存在插入空再看上级如果不存在还插入空直到根"0"
while (colId.indexOf(Constants.VAL_SPLIT_CHAR) > -1) {
colId = colId.substring(0, colId.lastIndexOf(Constants.VAL_SPLIT_CHAR));
if (!addParentNodeTreeMapKey(reMap, colId)) {
break;
}
}
}
/***
* 补充父级调度链路各节点信息
*
* @param reMap
* @param colId
* @return
*/
private static boolean addParentNodeTreeMapKey(Map<String, BuriedPointEntry> reMap, String colId) {
if (reMap.containsKey(colId)) {
logger.info("key hash exist: {}", colId);
return false;
} else {
// 增加虚拟节点
reMap.put(colId, BuriedPointEntry.addLostBuriedPointEntry(colId));
// 根据当前Id查找上级如果不存在插入空再看上级如果不存在还插入空直到根"0"
while (colId.indexOf(Constants.VAL_SPLIT_CHAR) > -1) {
colId = colId.substring(0, colId.lastIndexOf(Constants.VAL_SPLIT_CHAR));
if (!addParentNodeTreeMapKey(reMap, colId)) {
break;
}
}
return false;
}
}
/**
* 测试读取hbase 测试自动补充父级节点 测试排序
*
* @throws IOException
*
*/
@Test
public void testSelectByTraceId() throws IOException {
BuriedPointSDAO sdao = new BuriedPointSDAO();
Map<String, BuriedPointEntry> bpe = sdao.queryLogByTraceId(Constants.TABLE_NAME_CHAIN,
"6305eb1d1e1b46529a7eb57912a5766e123");
List<BuriedPointEntry> keyList = new ArrayList<BuriedPointEntry>();
keyList.addAll(bpe.values());
Collections.sort(keyList, new Comparator<BuriedPointEntry>() {
@Override
public int compare(BuriedPointEntry arg0, BuriedPointEntry arg1) {
return arg0.getColId().compareTo(arg1.getColId());
}
});
int m = 1;
for (BuriedPointEntry tmpEntry : keyList) {
logger.info("sort result level:{} : {}", m++, tmpEntry);
}
}
/***
* 深度补全测试
*
* @throws IOException
*/
@Test
public void testGenTreeMapKey() throws IOException {
StringBuffer sb = new StringBuffer("0");
/***
* 深度测试 level 5 [ 11ms ] level 10[ 11ms ] level 15[ 11ms ] level 20[
* 12ms ] level 50[ 12ms ] level 100[ 12ms ] level 500[ 12ms ] level
* 1000[ 16ms ] level 2000[ 28ms ] level 5000[ 144ms ] level10000[ 445ms
* ]
*/
for (int i = 1; i < 10000; i++) {
sb.append(".0");
}
String colId = sb.toString();
BuriedPointEntry tmpEntry = null;
Map<String, BuriedPointEntry> reMap = new HashMap<String, BuriedPointEntry>();
long startTime = System.currentTimeMillis();
logger.info("start time : {}", startTime);
addCurNodeTreeMapKey(reMap, colId, tmpEntry);
long endTime = System.currentTimeMillis();
logger.info("end time : {}", endTime);
logger.info("run time : {} ms", (endTime - startTime));
// List<String> keyList = new ArrayList<String>();
// keyList.addAll(reMap.keySet());
// Collections.sort(keyList);
// int m = 1;
// for (String str : keyList) {
// logger.info("sort result level:{} : {}", m++, str);
// }
}
/***
* collection sort 性能测试
*
* @param args
*/
@Test
public void testSortList() {
List<String> StrList = new ArrayList<String>();
Random random = new Random(System.currentTimeMillis());
StrList.add("0");
/***
* Collections.sort(StrList)性能 1000条/19 ms 10000条/42 ms 100000条/129 ms
* 1000000条/1070 ms
*/
for (int m = 0; m < 1000; m++) {
String radNum = "" + Math.abs(random.nextLong());
StringBuffer tmpBf = new StringBuffer("0");
for (int n = 0; n < radNum.length(); n++) {
tmpBf.append(".").append(radNum.charAt(n));
}
StrList.add(tmpBf.toString());
}
long startTime = System.currentTimeMillis();
logger.info("start time : {}", startTime);
Collections.sort(StrList);
long endTime = System.currentTimeMillis();
logger.info("end time : {}", endTime);
logger.info("run time : {} ms", (endTime - startTime));
// int i = 1;
// for (String tmpStr : StrList) {
// logger.info("sort {} : {}", i++, tmpStr);
// }
}
}

View File

@ -1,104 +1,172 @@
package com.ai.cloud.vo.mvo;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.ai.cloud.util.Constants;
/***
* hbase存储的链路信息模型
*
* @author tz
* @date 2015年11月18日 下午5:45:14
* @version V0.1
*/
public class BuriedPointEntry {
private String traceId;
private String parentLevel;
private int levelId;
private String viewPointId;
private Date startDate;
private long cost;
private String address;
private byte statusCode = 0;
private String exceptionStack;
private char spanType;
private boolean isReceiver = false;
private String businessKey;
private String processNo;
private String traceId;
private String parentLevel;
private int levelId;
private String viewPointId;
private long startDate;
private long cost;
private String address;
private char statusCode = Constants.STATUS_CODE_9;
private String exceptionStack;
private char spanType;
private boolean isReceiver = false;
private String businessKey;
private String processNo;
private String colId;
private long endDate;
private List<TimeLineEntry> timeLineList = new ArrayList<TimeLineEntry>();
private BuriedPointEntry() {
private BuriedPointEntry() {
}
}
public String getTraceId() {
return traceId;
}
public String getTraceId() {
return traceId;
}
public String getParentLevel() {
return parentLevel;
}
public String getParentLevel() {
return parentLevel;
}
public int getLevelId() {
return levelId;
}
public int getLevelId() {
return levelId;
}
public String getViewPointId() {
return viewPointId;
}
public String getViewPointId() {
return viewPointId;
}
public Date getStartDate() {
return startDate;
}
public long getStartDate() {
return startDate;
}
public long getCost() {
return cost;
}
public long getCost() {
return cost;
}
public String getAddress() {
return address;
}
public String getAddress() {
return address;
}
public byte getStatusCode() {
return statusCode;
}
public char getStatusCode() {
return statusCode;
}
public String getExceptionStack() {
return exceptionStack;
}
public String getExceptionStack() {
return exceptionStack;
}
public char getSpanType() {
return spanType;
}
public char getSpanType() {
return spanType;
}
public boolean isReceiver() {
return isReceiver;
}
public boolean isReceiver() {
return isReceiver;
}
public String getBusinessKey() {
return businessKey;
}
public String getBusinessKey() {
return businessKey;
}
public String getProcessNo() {
return processNo;
}
public String getProcessNo() {
return processNo;
}
public static BuriedPointEntry convert(String str) {
BuriedPointEntry result = new BuriedPointEntry();
String[] fieldValues = str.split("-");
result.traceId = fieldValues[0].trim();
result.parentLevel = fieldValues[1].trim();
result.levelId = Integer.valueOf(fieldValues[2]);
result.viewPointId = fieldValues[3].trim();
result.startDate = new Date(Long.valueOf(fieldValues[4]));
result.cost = Long.parseLong(fieldValues[5]);
result.address = fieldValues[6].trim();
result.exceptionStack = fieldValues[7].trim();
result.spanType = fieldValues[8].charAt(0);
result.isReceiver = Boolean.getBoolean(fieldValues[9]);
result.businessKey = fieldValues[10].replace('-', '^').trim();
result.processNo = fieldValues[11].trim();
return result;
}
public String getColId() {
return colId;
}
public void setColId(String colId) {
this.colId = colId;
}
public long getEndDate() {
return endDate;
}
public List<TimeLineEntry> getTimeLineList() {
return timeLineList;
}
private static BuriedPointEntry convert(String str) {
BuriedPointEntry result = new BuriedPointEntry();
String[] fieldValues = str.split("\\^\\~");
result.traceId = fieldValues[0].trim();
result.parentLevel = fieldValues[1].trim();
result.levelId = Integer.valueOf(fieldValues[2]);
result.viewPointId = fieldValues[3].trim();
result.startDate = Long.valueOf(fieldValues[4]);
result.cost = Long.parseLong(fieldValues[5]);
result.address = fieldValues[6].trim();
result.statusCode = fieldValues[7].charAt(0);
result.exceptionStack = fieldValues[8].trim();
result.spanType = fieldValues[9].charAt(0);
result.isReceiver = Boolean.getBoolean(fieldValues[10]);
result.businessKey = fieldValues[11].trim();
result.processNo = fieldValues[12].trim();
return result;
}
/***
* 增加时间轴信息
* @param startDate
* @param cost
*/
public void addTimeLine(long startDate, long cost) {
timeLineList.add(new TimeLineEntry(startDate, cost));
}
public static BuriedPointEntry convert(String str, String colId) {
BuriedPointEntry result = convert(str);
result.addTimeLine(result.startDate, result.cost);
result.colId = colId;
result.endDate = result.startDate + result.cost;
return result;
}
/***
* 补充丢失的链路信息
*
* @param colId
* @return
*/
public static BuriedPointEntry addLostBuriedPointEntry(String colId) {
BuriedPointEntry result = new BuriedPointEntry();
result.colId = colId;
if (colId.indexOf(Constants.VAL_SPLIT_CHAR) > -1) {
result.parentLevel = colId.substring(0, colId.lastIndexOf(Constants.VAL_SPLIT_CHAR));
} else {
result.parentLevel = "";
}
result.timeLineList.add(new TimeLineEntry());
// 其它默认值
return result;
}
@Override
public String toString() {
return "BuriedPointEntry [traceId=" + traceId + ", parentLevel=" + parentLevel + ", levelId=" + levelId
+ ", viewPointId=" + viewPointId + ", startDate=" + startDate + ", cost=" + cost + ", address="
+ address + ", statusCode=" + statusCode + ", exceptionStack=" + exceptionStack + ", spanType="
+ spanType + ", isReceiver=" + isReceiver + ", businessKey=" + businessKey + ", processNo=" + processNo
+ "]";
return "BuriedPointEntry [colId=" + colId + ", traceId=" + traceId + ", parentLevel=" + parentLevel
+ ", levelId=" + levelId + ", viewPointId=" + viewPointId + ", startDate=" + startDate + ", cost="
+ cost + ", address=" + address + ", statusCode=" + statusCode + ", exceptionStack=" + exceptionStack
+ ", spanType=" + spanType + ", isReceiver=" + isReceiver + ", businessKey=" + businessKey
+ ", processNo=" + processNo + "]";
}
}

View File

@ -0,0 +1,43 @@
/**
*
*/
package com.ai.cloud.vo.mvo;
/**
*
* 支持当前节点为RPC调用时可以在一个tr中展现多个调用时间轴
*
* @author tz
* @date 2015年11月19日 下午3:45:31
* @version V0.1
*/
public class TimeLineEntry {
private long startTime = 0l;
private long cost = 0l;
public TimeLineEntry(){
}
public TimeLineEntry(long startTime, long cost){
this.startTime = startTime;
this.cost = cost;
}
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getCost() {
return cost;
}
public void setCost(long cost) {
this.cost = cost;
}
}

View File

@ -1,4 +1,4 @@
<#import "./marco/common.ftl" as common>
<#import "./lib/ai.cloud/common.ftl" as common>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
@ -35,7 +35,7 @@
</div>
</div>
<div class="container">
<div>
<div class="text-center" style="height: 600px">
<iframe id="showTraceLog" border=2 frameborder=0 width=100%
height=100% marginheight=0 marginwidth=0 scrolling=yes src=""></iframe>

View File

@ -0,0 +1,107 @@
<#-- importJavaScript -->
<#macro importJavaScript>
<script src="${base}/js/jquery/jquery-2.1.4.js"></script>
<script src="${base}/js/jquery/jquery-ui-1.11.4.js"></script>
<script src="${base}/js/jquery/jquery.treetable-3.2.0.js"></script>
<script src="${base}/js/bootstrap.min-3.3.5.js"></script>
</#macro>
<#-- importMenuInfo -->
<#macro importMenuInfo menuInfo>
<ul class="nav navbar-nav">
<#assign text>
${menuInfo}
</#assign>
<#assign json=text?eval />
<#if json.isLogin == '1'>
<li><a name="menuUrl" href="#" url="user/useDoc/${json.uid}">使用说明</a></li>
<li><a name="menuUrl" href="#" url="user/">告警配置</a></li>
</#if>
</ul>
</#macro>
<#-- importSearchInfo -->
<#macro importSearchInfo isLogin>
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<#if isLogin == '1'>
<input id="srchKey" type="text" class="form-control" style="width: 450px" placeholder="TraceId">
<#else>
<input id="srchKey" type="text" class="form-control" style="width: 750px" placeholder="TraceId">
</#if>
</div>
<button id="srchBtn" type="button" class="btn btn-default">Search</button>
</form>
</#macro>
<#-- importUserInfo -->
<#macro importUserInfo userInfo>
<ul class="nav navbar-nav navbar-right">
<#assign text>
${userInfo}
</#assign>
<#assign json=text?eval />
<#if json.isLogin == '1'>
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false"> ${json.userName} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a name="menuUrl" href="#" url="user/setting/${json.uid}">设置</a></li>
<li role="separator" class="divider"></li>
<li><a name="menuUrl" href="#" url="logout">退出</a></li>
</ul>
</li>
<#else>
<li><a name="menuUrl" href="#" url="login">登录</a></li>
</#if>
</ul>
</#macro>
<#-- dealTraceLog -->
<#macro dealTraceLog>
<#if valueList??>
<div id="row">
<div class="col-md-12">
<table id="example-advanced">
<caption>
<a href="#" onclick="jQuery('#example-advanced').treetable('expandAll'); return false;">Expand all</a>
&nbsp;
<a href="#" onclick="jQuery('#example-advanced').treetable('collapseAll'); return false;">Collapse all</a>
</caption>
<thead>
<tr>
<th class="col-md-4" style="width: 16%">调用序列</th>
<th class="col-md-1" style="width: 4%">类型</th>
<th class="col-md-1" style="width: 4%">状态</th>
<th class="col-md-3" style="width: 10%">业务信息</th>
<th class="col-md-2" style="width: 8%">主机信息</th>
<th class="col-md-3" style="width: 16%">时间轴</th>
</tr>
</thead>
<tbody>
<#list valueList as logInfo>
<#if logInfo.colId == "0">
<tr data-tt-id='${logInfo.colId!}'>
<#else>
<tr data-tt-id='${logInfo.colId!}' data-tt-parent-id='${logInfo.parentLevel!}'>
</#if>
<td><b>${logInfo.viewPointId!}</b></td>
<td>${spanTypeMap[logInfo.spanType]!'-'}</td>
<td>${statusCodeMap[logInfo.statusCode]!}</td>
<td>${logInfo.businessKey!}</td>
<td>${logInfo.address!}</td>
<td>
<#assign totalTime=(endTime-beginTime)>
<#list logInfo.timeLineList as log>
<div class="progress" beginTime="${beginTime}" endTime="${endTime}" total_time="${totalTime}" cost="${log.cost}" curStartTime="${log.startTime}" beforePer="${100*(log.startTime-beginTime)/totalTime}" curPer="${100*log.cost/33?int}">
<div class="progress-bar" style="width: ${100*(log.startTime-beginTime)/totalTime}%"></div>
<div class="progress-bar progress-bar-info" style="min-width: ${100*log.cost/totalTime}%;">${log.cost}ms</div></div>
</#list>
</td>
</#list>
</tbody>
</table>
</div>
</div>
</#if>
</#macro>

View File

@ -1,4 +1,4 @@
<#import "./marco/common.ftl" as common>
<#import "./lib/ai.cloud/common.ftl" as common>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
@ -8,11 +8,11 @@
<meta name="generator" content="Bootply" />
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1">
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="${base}/css/bootstrap.min.css" rel="stylesheet">
<!--[if lt IE 9]>
<script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link href="css/login.css" rel="stylesheet">
<link href="${base}/css/login.css" rel="stylesheet">
</head>
<body>
<div class="container">

View File

@ -1,62 +0,0 @@
<#-- script -->
<#macro importJavaScript>
<script src="${base}/js/jquery/jquery-2.1.4.js"></script>
<script src="${base}/js/jquery/jquery-ui-1.11.4.js"></script>
<script src="${base}/js/jquery/jquery.treetable-3.2.0.js"></script>
<script src="${base}/js/bootstrap.min-3.3.5.js"></script>
</#macro>
<#-- menuInfo -->
<#macro importMenuInfo menuInfo>
<ul class="nav navbar-nav">
<#assign text>
${menuInfo}
</#assign>
<#assign json=text?eval />
<#if json.isLogin == '1'>
<li><a name="menuUrl" href="#" url="user/useDoc/${json.uid}">使用说明</a></li>
<li><a name="menuUrl" href="#" url="user/">告警配置</a></li>
<#else>
</#if>
</ul>
</#macro>
<#-- SearchInfo -->
<#macro importSearchInfo isLogin>
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<#if isLogin == '1'>
<input id="srchKey" type="text" class="form-control" style="width: 450px" placeholder="TraceId">
<#else>
<input id="srchKey" type="text" class="form-control" style="width: 750px" placeholder="TraceId">
</#if>
</div>
<button id="srchBtn" type="button" class="btn btn-default">Search</button>
</form>
</#macro>
<#-- userInfo -->
<#macro importUserInfo userInfo>
<ul class="nav navbar-nav navbar-right">
<#assign text>
${userInfo}
</#assign>
<#assign json=text?eval />
<#if json.isLogin == '1'>
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false"> ${json.userName} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a name="menuUrl" href="#" url="user/setting/${json.uid}">设置</a></li>
<li role="separator" class="divider"></li>
<li><a name="menuUrl" href="#" url="logout">退出</a></li>
</ul>
</li>
<#else>
<li><a name="menuUrl" href="#" url="login">登录</a></li>
</#if>
</ul>
</#macro>

View File

@ -1,5 +1,6 @@
<#import "./marco/common.ftl" as common>
<#import "./lib/ai.cloud/common.ftl" as common>
<!DOCTYPE html>
<html lang="zh-CN">
<html>
<head>
<meta charset="utf-8">
@ -8,211 +9,17 @@
<link rel="stylesheet" href="${base}/css/jquery.treetable.theme.default.css" />
<link rel="stylesheet" href="${base}/css/bootstrap.css" />
<link rel="stylesheet" href="${base}/css/traceLog.css" />
</head>
<body>
<div id="row">
<div class="col-md-12">
<table id="example-advanced">
<caption>
<a href="#" onclick="jQuery('#example-advanced').treetable('expandAll'); return false;">Expand all</a>
&nbsp;
<a href="#" onclick="jQuery('#example-advanced').treetable('collapseAll'); return false;">Collapse all</a>
</caption>
<thead>
<tr>
<th class="col-md-3">应用名</th>
<th class="col-md-1">类型</th>
<th class="col-md-1">状态</th>
<th class="col-md-1">大小</th>
<th class="col-md-3">服务/方法</th>
<th class="col-md-3">时间轴</th>
</tr>
</thead>
<tbody>
<tr data-tt-id='1'>
<td>
<b>tf_buy</b>
</td>
<td>
TRACE
</td>
<td>
OK
</td>
<td>
-
</td>
<td>
http://buy.taobao.com/auction/buy_now.html
</td>
<td>
<div class="progress">
<div class="progress-bar progress-bar-success progress-bar-striped" style="width:50%">
239ms
</div>
</div>
</td>
</tr>
<tr data-tt-id='1-1' data-tt-parent-id='1'>
<td>
<b>tradeplatform</b>
</td>
<td>
HSF
</td>
<td>
OK
</td>
<td>
670B
</td>
<td>
tc.TcTradeService@getOutOrderSwqIdByBuyerId~1
</td>
<td>
<div class="progress">
<div class="progress-bar" style="width: 2%">
</div>
<div class="progress-bar progress-bar-success progress-bar-striped" style="min-width: 2%;">
0ms
</div>
</div>
</td>
</tr>
<tr data-tt-id='1-2' data-tt-parent-id='1'>
<td>
<b>tradeplatform</b>
</td>
<td>
HSF
</td>
<td>
OK
</td>
<td>
8.0KB
</td>
<td>
trade.ICreatingOrderService@createOrdersForTaobao~R
</td>
<td>
<div class="progress">
<div class="progress-bar" style="width: 2%">
</div>
<div class="progress-bar progress-bar-warning progress-bar-striped" style="min-width: 2%;">
</div>
<div class="progress-bar progress-bar-success progress-bar-striped" style="min-width: 8%;">
46ms
</div>
<div class="progress-bar progress-bar-info progress-bar-striped" style="min-width: 2%;">
</div>
</div>
</td>
</tr>
<tr data-tt-id='1-2-1' data-tt-parent-id='1-2'>
<td>
<b>Itemcenter</b>
</td>
<td>
HSF
</td>
<td>
OK
</td>
<td>
5.0KB
</td>
<td>
item.IItermQueryService@queryItermAndSkWithPVToText~L
</td>
<td>
<div class="progress">
<div class="progress-bar" style="width: 12%">
</div>
<div class="progress-bar progress-bar-success progress-bar-striped" style="min-width: 5%;">
8ms
</div>
</div>
</td>
</tr>
<tr data-tt-id='1-2-2' data-tt-parent-id='1-2'>
<td>
<b>Itemcenter</b>
</td>
<td>
HSF
</td>
<td>
OK
</td>
<td>
3.0KB
</td>
<td>
item.SpuService@getSpu~l
</td>
<td>
<div class="progress">
<div class="progress-bar" style="width: 17%">
</div>
<div class="progress-bar progress-bar-success progress-bar-striped" style="min-width: 2%;">
3ms
</div>
</div>
</td>
</tr>
<tr data-tt-id='2'>
<td>
<b>misccenter</b>
</td>
<td>
HSF
</td>
<td>
OK
</td>
<td>
3.0KB
</td>
<td>
misccenter.EcardOrderService@insertEcardOrder~E
</td>
<td>
<div class="progress">
<div class="progress-bar" style="width: 19%">
</div>
<div class="progress-bar progress-bar-success progress-bar-striped" style="min-width: 4%;">
6ms
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- show traceLogInfo -->
<@common.dealTraceLog />
<!-- script references -->
<@common.importJavaScript />
<script>
var table = $('#example-advanced').children();
$("#example-advanced").treetable({ expandable: true });
$("#example-advanced").treetable({ expandable: true , indent : 10, clickableNodeNames : true});
$("#example-advanced tr").click(function() {
var selected = $(this).hasClass("highlight");

View File

@ -1,4 +1,4 @@
function changeFrameUrl(url){
function changeFrameUrl(url) {
console.info('showTraceLog iframe url change: ' + url);
$("#showTraceLog").attr("src", url);
}
@ -8,25 +8,27 @@ $().ready(function() {
var baseUrl = $("#baseUrl").val();
var traceId = $("#traceId").val();
/** 搞个默认值测试*/
traceId = "933b360f94294833b6a82351d4ded676123";
changeFrameUrl("");
/** init page */
if(traceId != '' && traceId.length > 0){
if (traceId != '' && traceId.length > 0) {
$("#srchKey").val(traceId);
var srchKey = $("#srchKey").val();
if (srchKey != "") {
changeFrameUrl(baseUrl + "showTraceLog");
changeFrameUrl(baseUrl + "showTraceLog/" + srchKey);
}
}else{
} else {
$("#srchKey").val("");
}
/** bind srchBtn */
$("#srchBtn").bind("click", function() {
var srchKey = $("#srchKey").val();
if (srchKey != "") {
changeFrameUrl(baseUrl + "showTraceLog");
changeFrameUrl(baseUrl + "showTraceLog/" + srchKey);
}
});
@ -35,5 +37,5 @@ $().ready(function() {
changeFrameUrl(baseUrl + $(this).attr("url"));
});
});
});