mirror of
https://github.com/apache/rocketmq-dashboard.git
synced 2025-09-11 20:15:44 +08:00
* 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:
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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>
|
||||||
|
Reference in New Issue
Block a user