[ISSUE #745] Message trace data table improvement (#746)

* Message trace data table improvement
1. Send Message Trace
1.1 Send Message Info
1.2 Check Transaction Info
2. Consume Message Trace
2.1 Message Trace (group by subscription group )
3. X Axis time format(keep two decimal places)
4. use min instead of m
This commit is contained in:
StyleTang
2021-07-21 09:01:48 +08:00
committed by GitHub
parent 38c1b97589
commit bb08d466f9
3 changed files with 175 additions and 18 deletions

View File

@@ -117,7 +117,7 @@ public class MessageTraceServiceImpl implements MessageTraceService {
} }
} }
if (producerNode != null) { if (producerNode != null) {
producerNode.setTransactionNodeList(transactionNodeList); producerNode.setTransactionNodeList(sortTraceNodeListByBeginTimestamp(transactionNodeList));
} }
messageTraceGraph.setProducerNode(producerNode); messageTraceGraph.setProducerNode(producerNode);
messageTraceGraph.setSubscriptionNodeList(buildSubscriptionNodeList(requestIdTracePairMap)); messageTraceGraph.setSubscriptionNodeList(buildSubscriptionNodeList(requestIdTracePairMap));
@@ -149,9 +149,10 @@ public class MessageTraceServiceImpl implements MessageTraceService {
} }
return subscriptionTraceNodeMap.entrySet().stream() return subscriptionTraceNodeMap.entrySet().stream()
.map((Function<Map.Entry<String, List<TraceNode>>, SubscriptionNode>) subscriptionEntry -> { .map((Function<Map.Entry<String, List<TraceNode>>, SubscriptionNode>) subscriptionEntry -> {
List<TraceNode> traceNodeList = subscriptionEntry.getValue();
SubscriptionNode subscriptionNode = new SubscriptionNode(); SubscriptionNode subscriptionNode = new SubscriptionNode();
subscriptionNode.setSubscriptionGroup(subscriptionEntry.getKey()); subscriptionNode.setSubscriptionGroup(subscriptionEntry.getKey());
subscriptionNode.setConsumeNodeList(subscriptionEntry.getValue()); subscriptionNode.setConsumeNodeList(sortTraceNodeListByBeginTimestamp(traceNodeList));
return subscriptionNode; return subscriptionNode;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
@@ -186,4 +187,9 @@ public class MessageTraceServiceImpl implements MessageTraceService {
traceNode.setEndTimeStamp(messageTraceView.getTimeStamp() + messageTraceView.getCostTime()); traceNode.setEndTimeStamp(messageTraceView.getTimeStamp() + messageTraceView.getCostTime());
return traceNode; return traceNode;
} }
private List<TraceNode> sortTraceNodeListByBeginTimestamp(List<TraceNode> traceNodeList) {
traceNodeList.sort((o1, o2) -> -Long.compare(o1.getBeginTimeStamp(), o2.getBeginTimeStamp()));
return traceNodeList;
}
} }

View File

@@ -16,11 +16,14 @@
*/ */
var module = app; var module = app;
const PRODUCER_COLOR = '#029e02'
const SUCCESS_COLOR = '#75d874'; const SUCCESS_COLOR = '#75d874';
const ERROR_COLOR = 'red'; const ERROR_COLOR = 'red';
const TRANSACTION_COMMIT_COLOR = SUCCESS_COLOR; const TRANSACTION_COMMIT_COLOR = SUCCESS_COLOR;
const TRANSACTION_ROLLBACK_COLOR = ERROR_COLOR; const TRANSACTION_ROLLBACK_COLOR = ERROR_COLOR;
const SHOW_GRAPH = 'Show Graph';
const HIDE_GRAPH = 'Hide Graph';
const SHOW_GRAPH_TRACE_DATA = 'Show Graph Trace Data';
const SHOW_ORIGINAL_TRACE_DATA = 'Show Original Trace Data';
const TRANSACTION_UNKNOWN_COLOR = 'grey' const TRANSACTION_UNKNOWN_COLOR = 'grey'
const TIME_FORMAT_PATTERN = "YYYY-MM-DD HH:mm:ss.SSS"; const TIME_FORMAT_PATTERN = "YYYY-MM-DD HH:mm:ss.SSS";
const DEFAULT_DISPLAY_DURATION = 10 * 1000 const DEFAULT_DISPLAY_DURATION = 10 * 1000
@@ -118,7 +121,9 @@ module.controller('messageTraceController', ['$scope', '$routeParams', 'ngDialog
module.controller('messageTraceDetailViewDialogController', ['$scope', '$timeout', 'ngDialog', '$http', 'Notification', function ($scope, $timeout, ngDialog, $http, Notification) { module.controller('messageTraceDetailViewDialogController', ['$scope', '$timeout', 'ngDialog', '$http', 'Notification', function ($scope, $timeout, ngDialog, $http, Notification) {
$scope.displayGraph = false; $scope.displayGraph = false;
$scope.graphButtonName = 'Show Graph'; $scope.showGraphData = true;
$scope.graphButtonName = SHOW_GRAPH;
$scope.traceDataButtonName = SHOW_ORIGINAL_TRACE_DATA;
$scope.displayMessageTraceGraph = function (messageTraceGraph) { $scope.displayMessageTraceGraph = function (messageTraceGraph) {
let dom = document.getElementById("messageTraceGraph"); let dom = document.getElementById("messageTraceGraph");
$scope.messageTraceGraph = echarts.init(dom); $scope.messageTraceGraph = echarts.init(dom);
@@ -139,9 +144,9 @@ module.controller('messageTraceDetailViewDialogController', ['$scope', '$timeout
}) })
} }
function buildNodeColor(traceNode, index) { function buildNodeColor(traceNode) {
let nodeColor = SUCCESS_COLOR; let nodeColor = SUCCESS_COLOR;
if (traceNode.transactionState) { if (traceNode.transactionState != null) {
switch (traceNode.transactionState) { switch (traceNode.transactionState) {
case 'COMMIT_MESSAGE': case 'COMMIT_MESSAGE':
return TRANSACTION_COMMIT_COLOR; return TRANSACTION_COMMIT_COLOR;
@@ -156,9 +161,6 @@ module.controller('messageTraceDetailViewDialogController', ['$scope', '$timeout
if (traceNode.status !== 'success') { if (traceNode.status !== 'success') {
nodeColor = ERROR_COLOR; nodeColor = ERROR_COLOR;
} }
if (index === messageGroups.length - 1) {
nodeColor = PRODUCER_COLOR;
}
return nodeColor; return nodeColor;
} }
@@ -168,14 +170,19 @@ module.controller('messageTraceDetailViewDialogController', ['$scope', '$timeout
return duration + 'ms'; return duration + 'ms';
duration /= 1000; duration /= 1000;
if (duration < 60) if (duration < 60)
return duration + 's'; return timeFormat(duration, 's');
duration /= 60; duration /= 60;
if (duration < 60) if (duration < 60)
return duration + 'm'; return timeFormat(duration, 'min');
duration /= 60; duration /= 60;
return duration + 'h'; return timeFormat(duration, 'h');
} }
function timeFormat(duration, unit) {
return duration.toFixed(2) + unit;
}
function buildTraceInfo(itemName, itemValue) { function buildTraceInfo(itemName, itemValue) {
if (itemValue) { if (itemValue) {
return `${itemName}: ${itemValue}<br />` return `${itemName}: ${itemValue}<br />`
@@ -210,7 +217,7 @@ module.controller('messageTraceDetailViewDialogController', ['$scope', '$timeout
], ],
itemStyle: { itemStyle: {
normal: { normal: {
color: buildNodeColor(traceNode, index), color: buildNodeColor(traceNode),
opacity: 1 opacity: 1
} }
}, },
@@ -329,15 +336,23 @@ module.controller('messageTraceDetailViewDialogController', ['$scope', '$timeout
$scope.showGraph = function () { $scope.showGraph = function () {
$scope.displayGraph = !$scope.displayGraph; $scope.displayGraph = !$scope.displayGraph;
if ($scope.displayGraph) { if ($scope.displayGraph) {
$scope.graphButtonName = 'Hide Graph'; $scope.graphButtonName = HIDE_GRAPH;
$scope.displayMessageTraceGraph($scope.ngDialogData); $scope.displayMessageTraceGraph($scope.ngDialogData);
} else { } else {
$scope.messageTraceGraph.dispose(); $scope.messageTraceGraph.dispose();
$scope.graphButtonName = 'Show Graph'; $scope.graphButtonName = SHOW_GRAPH;
} }
console.log("here is my data", $scope.ngDialogData)
}; };
$scope.changeTraceDataFormat = function () {
$scope.showGraphData = !$scope.showGraphData;
if ($scope.showGraphData) {
$scope.traceDataButtonName = SHOW_ORIGINAL_TRACE_DATA;
} else {
$scope.traceDataButtonName = SHOW_GRAPH_TRACE_DATA;
}
}
function initGraph() { function initGraph() {
$timeout(function () { $timeout(function () {
if (document.getElementById('messageTraceGraph') == null) { if (document.getElementById('messageTraceGraph') == null) {

View File

@@ -131,13 +131,149 @@
<script type="text/ng-template" id="messageTraceDetailViewDialog"> <script type="text/ng-template" id="messageTraceDetailViewDialog">
<md-content class="md-padding"> <md-content class="md-padding">
<div class="row" > <div class="row">
<button class="ngdialog-button ngdialog-button-primary" type="button"
ng-click="changeTraceDataFormat()">{{traceDataButtonName}}
</button>
<button class="ngdialog-button ngdialog-button-primary" type="button" <button class="ngdialog-button ngdialog-button-primary" type="button"
ng-click="showGraph()">{{graphButtonName}} ng-click="showGraph()">{{graphButtonName}}
</button> </button>
</div> </div>
<div class="row" ng-hide="!displayGraph" id="messageTraceGraph" style="height: 500px; width: 1024px"></div> <div class="row" ng-hide="!displayGraph" id="messageTraceGraph" style="height: 500px; width: 1024px"></div>
<div class="row"> <div class="row" ng-hide="!showGraphData">
<div id="producerSendMessage" class="container">
<a>
<h3 data-toggle="collapse" data-target="#sendMessageTrace">
Send Message Trace
</h3>
</a>
<div id="sendMessageTrace" class="collapse in">
<div ng-if="ngDialogData.producerNode == null">
No Producer Trace Data
</div>
<div id="producerTrace" ng-if="ngDialogData.producerNode != null">
<h4>Send Message Info</h4>
<table class="table table-bordered">
<tr>
<th class="text-center">topic</th>
<th class="text-center">groupName</th>
<th class="text-center">keys</th>
<th class="text-center">tags</th>
<th class="text-center">msgId</th>
</tr>
<tr>
<td class="text-center">{{ngDialogData.producerNode.topic}}</td>
<td class="text-center">{{ngDialogData.producerNode.groupName}}</td>
<td class="text-center">{{ngDialogData.producerNode.keys}}</td>
<td class="text-center">{{ngDialogData.producerNode.tags}}</td>
<td class="text-center">{{ngDialogData.producerNode.msgId}}</td>
</tr>
<tr>
<th class="text-center">beginTimeStamp</th>
<th class="text-center">endTimeStamp</th>
<th class="text-center">costTime</th>
<th class="text-center">msgType</th>
<th class="text-center">offSetMsgId</th>
</tr>
<tr>
<td class="text-center">
{{ngDialogData.producerNode.traceNode.beginTimeStamp | date:'yyyy-MM-dd HH:mm:ss.sss'}}
</td>
<td class="text-center">
{{ngDialogData.producerNode.traceNode.endTimeStamp | date:'yyyy-MM-dd HH:mm:ss.sss'}}
</td>
<td class="text-center">{{ngDialogData.producerNode.traceNode.costTime}} ms</td>
<td class="text-center">{{ngDialogData.producerNode.traceNode.msgType}}</td>
<td class="text-center">{{ngDialogData.producerNode.offSetMsgId}}</td>
</tr>
<tr>
<th class="text-center">clientHost</th>
<th class="text-center">storeHost</th>
<th class="text-center">retryTimes</th>
</tr>
<tr>
<td class="text-center">{{ngDialogData.producerNode.traceNode.clientHost}}</td>
<td class="text-center">{{ngDialogData.producerNode.traceNode.storeHost}}</td>
<td class="text-center">{{ngDialogData.producerNode.traceNode.retryTimes}}</td>
</tr>
</table>
<div id="producerTransaction"
ng-if="ngDialogData.producerNode.transactionNodeList.length > 0">
<h4>Check Transaction Info</h4>
<table class="table table-bordered">
<tr>
<th class="text-center">timeStamp</th>
<th class="text-center">transactionState</th>
<th class="text-center">fromTransactionCheck</th>
<th class="text-center">clientHost</th>
<th class="text-center">storeHost</th>
</tr>
<tr ng-repeat="transactionNode in ngDialogData.producerNode.transactionNodeList">
<td class="text-center">
{{transactionNode.beginTimeStamp | date:'yyyy-MM-dd HH:mm:ss.sss'}}
</td>
<td class="text-center">{{transactionNode.transactionState}}</td>
<td class="text-center">{{transactionNode.fromTransactionCheck}}</td>
<td class="text-center">{{transactionNode.clientHost}}</td>
<td class="text-center">{{transactionNode.storeHost}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div id="subscriptionConsumeMessage" class="container">
<a>
<h3 data-toggle="collapse" data-target="#consumeMessageTrace">
Consume Message Trace
</h3>
</a>
<div id="consumeMessageTrace" class="collapse in">
<div id="consumerTrace" ng-if="ngDialogData.subscriptionNodeList.length > 0">
<div ng-repeat="subscriptionNode in ngDialogData.subscriptionNodeList">
<div class="container">
<a>
<h3 data-toggle="collapse"
data-target="#subscriptionNode{{subscriptionNode.subscriptionGroup}}">
SubscriptionGroup : {{subscriptionNode.subscriptionGroup}}
</h3>
</a>
<div id="subscriptionNode{{subscriptionNode.subscriptionGroup}}" class="collapse in">
<table class="table table-bordered">
<tr>
<th class="text-center">beginTimeStamp</th>
<th class="text-center">endTimeStamp</th>
<th class="text-center">costTime</th>
<th class="text-center">status</th>
<th class="text-center">retryTimes</th>
<th class="text-center">clientHost</th>
<th class="text-center">storeHost</th>
</tr>
<tr ng-repeat="consumeNode in subscriptionNode.consumeNodeList">
<td class="text-center">
{{consumeNode.beginTimeStamp | date:'yyyy-MM-dd HH:mm:ss.sss'}}
</td>
<td class="text-center">
{{consumeNode.endTimeStamp | date:'yyyy-MM-dd HH:mm:ss.sss'}}
</td>
<td class="text-center">{{consumeNode.costTime}}</td>
<td class="text-center">{{consumeNode.status}}</td>
<td class="text-center">{{consumeNode.retryTimes}}</td>
<td class="text-center">{{consumeNode.clientHost}}</td>
<td class="text-center">{{consumeNode.storeHost}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
<div ng-if="ngDialogData.subscriptionNodeList.length == 0">
No Consumer Trace Data
</div>
</div>
</div>
</div>
<div class="row" ng-hide="showGraphData">
<table class="table table-bordered"> <table class="table table-bordered">
<tr> <tr>
<th class="text-center">Message ID</th> <th class="text-center">Message ID</th>