diff --git a/apollo-portal/src/main/resources/static/audit_log_trace_detail.html b/apollo-portal/src/main/resources/static/audit_log_trace_detail.html index e3363e39813..a3a1487a415 100644 --- a/apollo-portal/src/main/resources/static/audit_log_trace_detail.html +++ b/apollo-portal/src/main/resources/static/audit_log_trace_detail.html @@ -56,18 +56,7 @@

{{ 'ApolloAuditLog.TraceDetailTips' | translate }}

{{'ApolloAuditLog.TraceAuditLogTips' | translate }}
-
-

- {{detail.logDTO.opName}} - -

-
-
{{'ApolloAuditLog.SpanIdTips' | translate }}:{{detail.logDTO.spanId.substr(0,5)+'...'}}
-
{{'ApolloAuditLog.ParentSpan' | translate }}:{{findOpNameBySpanId(detail.logDTO.parentSpanId)}}
-
{{'ApolloAuditLog.FollowsFromSpan' | translate }}:{{findOpNameBySpanId(detail.logDTO.followsFromSpanId)}}
-
-
+
@@ -89,7 +78,7 @@

{{'ApolloAuditLog.OpType' | translate}}:{{showingDet
{{'ApolloAuditLog.Description' | translate}}:{{showingDetail.logDTO.description}}
-
+

{{'ApolloAuditLog.InfluenceEntity' | translate}}:

@@ -153,7 +142,7 @@

+ class="no-margin table table-striped table-hover table-bordered"> @@ -181,7 +170,7 @@
{{'ApolloAuditLog.NoDataInfluence' | translate }}
-
+

{{'ApolloAuditLog.NoTraceDetail' | translate }}

@@ -206,12 +195,13 @@

+ src="vendor/angular/angular-translate.2.18.1/angular-translate-loader-static-files.min.js"> + src="vendor/angular/angular-translate.2.18.1/angular-translate-storage-cookie.min.js"> + diff --git a/apollo-portal/src/main/resources/static/scripts/controller/AuditLogMenuController.js b/apollo-portal/src/main/resources/static/scripts/controller/AuditLogMenuController.js index 5a8c2773099..aad712df4fb 100644 --- a/apollo-portal/src/main/resources/static/scripts/controller/AuditLogMenuController.js +++ b/apollo-portal/src/main/resources/static/scripts/controller/AuditLogMenuController.js @@ -16,79 +16,109 @@ */ audit_log_menu_module.controller('AuditLogMenuController', ['$scope', '$window', '$translate', '$document', 'toastr', 'AppService', 'AppUtil', 'EventManager', 'AuditLogService', - auditLogMenuController] + auditLogMenuController] ); function auditLogMenuController($scope, $window, $translate, $document, toastr, AppService, AppUtil, EventManager, AuditLogService) { - $scope.auditEnabled = false; + $scope.auditEnabled = false; - $scope.auditLogList = []; - $scope.goToTraceDetailsPage = goToTraceDetailsPage; - $scope.searchByOpNameAndDate = searchByOpNameAndDate; - $scope.getMoreAuditLogs = getMoreAuditLogs; + $scope.auditLogList = []; + $scope.goToTraceDetailsPage = goToTraceDetailsPage; + $scope.searchByOpNameAndDate = searchByOpNameAndDate; + $scope.getMoreAuditLogs = getMoreAuditLogs; - $scope.page = 0; - var PAGE_SIZE = 10; + $scope.page = 0; + var PAGE_SIZE = 10; - $scope.opName = ''; - $scope.startDate = null; - $scope.endDate = null; - $scope.startDateFmt = null; - $scope.endDateFmt = null; + $scope.opName = ''; + $scope.startDate = null; + $scope.endDate = null; + $scope.startDateFmt = null; + $scope.endDateFmt = null; - $scope.hasLoadAll = false; + $scope.hasLoadAll = false; - $scope.options = []; - $scope.showSearchDropdown = false; + $scope.options = []; + $scope.showSearchDropdown = false; - $scope.showOptions = function(query) { - $scope.options = []; - searchAuditLogs(query); - }; + $scope.showOptions = function (query) { + $scope.options = []; + searchAuditLogs(query); + }; - $scope.selectOption = function(option) { - $scope.opName = option.opName; - $scope.showSearchDropdown = false; - }; + $scope.selectOption = function (option) { + $scope.opName = option.opName; + $scope.showSearchDropdown = false; + }; - init(); + init(); - function init() { - getAuditProperties(); - initSearchingMenu(); - } + function init() { + getAuditProperties(); + initSearchingMenu(); + } - function getAuditProperties() { - AuditLogService.get_properties().then(function (result) { - $scope.auditEnabled = result.enabled; - }); - } - - function initSearchingMenu() { - AuditLogService.find_all_logs($scope.page, PAGE_SIZE).then(function (result) { - if (!result || result.length < PAGE_SIZE) { - $scope.hasLoadAll = true; - } - if (result.length === 0) { - return; - } - $scope.auditLogList = $scope.auditLogList.concat(result); - }); - } + function getAuditProperties() { + AuditLogService.get_properties().then(function (result) { + $scope.auditEnabled = result.enabled; + }); + } - function searchByOpNameAndDate(opName, startDate, endDate) { - if (startDate !== null) { - $scope.startDateFmt = new Date(startDate).Format("yyyy-MM-dd hh:mm:ss.S"); + function initSearchingMenu() { + AuditLogService.find_all_logs($scope.page, PAGE_SIZE).then(function (result) { + if (!result || result.length < PAGE_SIZE) { + $scope.hasLoadAll = true; } - if (endDate !== null) { - $scope.endDateFmt = new Date(endDate).Format("yyyy-MM-dd hh:mm:ss.S"); + if (result.length === 0) { + return; } - $scope.auditLogList = []; - $scope.page = 0; - $scope.opName = opName; - $scope.startDate = startDate; - $scope.endDate = endDate; + $scope.auditLogList = $scope.auditLogList.concat(result); + }); + } + + function searchByOpNameAndDate(opName, startDate, endDate) { + if (startDate !== null) { + $scope.startDateFmt = new Date(startDate).Format("yyyy-MM-dd hh:mm:ss.S"); + } + if (endDate !== null) { + $scope.endDateFmt = new Date(endDate).Format("yyyy-MM-dd hh:mm:ss.S"); + } + $scope.auditLogList = []; + $scope.page = 0; + $scope.opName = opName; + $scope.startDate = startDate; + $scope.endDate = endDate; + AuditLogService.find_logs_by_opName( + $scope.opName, + $scope.startDateFmt, + $scope.endDateFmt, + $scope.page, + PAGE_SIZE + ).then(function (result) { + if (!result || result.length < PAGE_SIZE) { + $scope.hasLoadAll = true; + } + if (result.length === 0) { + return; + } + $scope.auditLogList = $scope.auditLogList.concat(result); + }); + } + + function getMoreAuditLogs() { + $scope.page = $scope.page + 1; + if ($scope.opName === '') { + AuditLogService.find_all_logs($scope.page, PAGE_SIZE).then(function (result) { + if (!result || result.length < PAGE_SIZE) { + $scope.hasLoadAll = true; + } + if (result.length === 0) { + return; + } + $scope.auditLogList = $scope.auditLogList.concat(result); + }); + } else { AuditLogService.find_logs_by_opName( $scope.opName, $scope.startDateFmt, @@ -96,80 +126,50 @@ function auditLogMenuController($scope, $window, $translate, $document, toastr, $scope.page, PAGE_SIZE ).then(function (result) { - if (!result || result.length < PAGE_SIZE) { - $scope.hasLoadAll = true; - } - if (result.length === 0) { - return; - } - $scope.auditLogList = $scope.auditLogList.concat(result); + if (!result || result.length < PAGE_SIZE) { + $scope.hasLoadAll = true; + } + if (result.length === 0) { + return; + } + $scope.auditLogList = $scope.auditLogList.concat(result); }); - } - - function getMoreAuditLogs() { - $scope.page = $scope.page + 1; - if($scope.opName === '') { - AuditLogService.find_all_logs($scope.page, PAGE_SIZE).then(function (result) { - if (!result || result.length < PAGE_SIZE) { - $scope.hasLoadAll = true; - } - if (result.length === 0) { - return; - } - $scope.auditLogList = $scope.auditLogList.concat(result); - }); - }else { - AuditLogService.find_logs_by_opName( - $scope.opName, - $scope.startDateFmt, - $scope.endDateFmt, - $scope.page, - PAGE_SIZE - ).then(function (result) { - if (!result || result.length < PAGE_SIZE) { - $scope.hasLoadAll = true; - } - if (result.length === 0) { - return; - } - $scope.auditLogList = $scope.auditLogList.concat(result); - }); - } - } - - function searchAuditLogs(query) { - AuditLogService.search_by_name_or_type_or_operator(query, 0, 20).then(function (result) { - result.forEach(function (log) { - var optionDisplay = log.opName + '-(' + log.opType + ').by:' + log.operator; - var option = { - id: log.id, - display: optionDisplay, - opName: log.opName - }; - $scope.options.push(option); - }); - $scope.showSearchDropdown = $scope.options.length > 0; + } + } + + function searchAuditLogs(query) { + AuditLogService.search_by_name_or_type_or_operator(query, 0, 20).then(function (result) { + result.forEach(function (log) { + var optionDisplay = log.opName + '-(' + log.opType + ').by:' + log.operator; + var option = { + id: log.id, + display: optionDisplay, + opName: log.opName + }; + $scope.options.push(option); }); - } + $scope.showSearchDropdown = $scope.options.length > 0; + }); + } - function goToTraceDetailsPage(traceId) { - $window.location.href = AppUtil.prefixPath() + "/audit_log_trace_detail.html?#traceId=" + traceId; - } + function goToTraceDetailsPage(traceId) { + $window.location.href = AppUtil.prefixPath() + "/audit_log_trace_detail.html?#traceId=" + traceId; + } - $document.on('click', function(event) { - if (!$scope.showSearchDropdown) { - return; - } + $document.on('click', function (event) { + if (!$scope.showSearchDropdown) { + return; + } - var target = angular.element(event.target); + var target = angular.element(event.target); - // 检查点击的目标是否是输入框或下拉栏,如果不是,则隐藏下拉栏 - if (!target.hasClass('form-control') && !target.hasClass('options-container')) { - $scope.$apply(function() { - $scope.showSearchDropdown = false; - }); - } - }); + // 检查点击的目标是否是输入框或下拉栏,如果不是,则隐藏下拉栏 + if (!target.hasClass('form-control') && !target.hasClass('options-container')) { + $scope.$apply(function () { + $scope.showSearchDropdown = false; + }); + } + }); } diff --git a/apollo-portal/src/main/resources/static/scripts/controller/AuditLogTraceDetailController.js b/apollo-portal/src/main/resources/static/scripts/controller/AuditLogTraceDetailController.js index 6e19f2ddcb0..45b4c6e6fee 100644 --- a/apollo-portal/src/main/resources/static/scripts/controller/AuditLogTraceDetailController.js +++ b/apollo-portal/src/main/resources/static/scripts/controller/AuditLogTraceDetailController.js @@ -16,142 +16,180 @@ */ audit_log_trace_detail_module.controller('AuditLogTraceDetailController', ['$scope', '$location', '$window', '$translate', 'toastr', 'AppService', 'AppUtil', 'EventManager', 'AuditLogService', - auditLogTraceDetailController] + auditLogTraceDetailController] ); -function auditLogTraceDetailController($scope, $location, $window, $translate, toastr, AppService, AppUtil, EventManager, AuditLogService) { - var params = AppUtil.parseParams($location.$$url); - $scope.traceId = params.traceId; - - $scope.traceDetails = []; - $scope.showingDetail = {}; - $scope.dataInfluenceEntities = []; - $scope.relatedDataInfluences = []; - $scope.relatedDataInfluencePage = 0; - $scope.relatedDataInfluenceHasLoadAll = true; - var RelatedDataInfluencePageSize = 10; - $scope.setShowingDetail = setShowingDetail; - $scope.showText = showText; - $scope.removeInClassFromLogDropDownExceptId = removeInClassFromLogDropDownExceptId; - $scope.findMoreRelatedDataInfluence = findMoreRelatedDataInfluence; - $scope.showRelatedDataInfluence = showRelatedDataInfluence; - $scope.findOpNameBySpanId = findOpNameBySpanId; - $scope.refreshDataInfluenceEntities = refreshDataInfluenceEntities; - - init(); - - function init() { - getTraceDetails(); - } - - function getTraceDetails() { - AuditLogService.find_trace_details($scope.traceId).then( - function (result) { - $scope.traceDetails = result; - } - ); - } - - function setShowingDetail(detail) { - $scope.showingDetail = detail; - refreshDataInfluenceEntities(); - } - - function removeInClassFromLogDropDownExceptId(id) { - $scope.relatedDataInfluences = []; - $scope.relatedDataInfluenceHasLoadAll = true; - - var elements = document.querySelectorAll('[id^="detail"]'); - elements.forEach(function (element) { - if(element.id !== 'detail'+id) { - element.classList.remove('in'); - } +function auditLogTraceDetailController($scope, $location, $window, $translate, toastr, AppService, AppUtil, EventManager, AuditLogService) { + var params = AppUtil.parseParams($location.$$url); + $scope.traceId = params.traceId; + + $scope.traceDetailsTree = []; + $scope.showingDetail = {}; + $scope.dataInfluenceEntities = []; + $scope.relatedDataInfluences = []; + $scope.relatedDataInfluencePage = 0; + $scope.relatedDataInfluenceHasLoadAll = true; + var RelatedDataInfluencePageSize = 10; + $scope.showText = showText; + $scope.findMoreRelatedDataInfluence = findMoreRelatedDataInfluence; + $scope.showRelatedDataInfluence = showRelatedDataInfluence; + $scope.refreshDataInfluenceEntities = refreshDataInfluenceEntities; + + init(); + + function init() { + buildTraceDetailsTree(); + } + + function buildTraceDetailsTree() { + AuditLogService.find_trace_details($scope.traceId).then( + function (result) { + $scope.traceDetails = result; + $scope.traceDetailsTree = buildTree($scope.traceDetails); + // 初始化 Bootstrap Treeview + $(document).ready(function () { + $('#treeview').treeview({ + color: "#252525", + showBorder: false, + data: $scope.traceDetailsTree, + levels: 99, + showTags: true, + onNodeSelected: function (event, data) { + changeShowingDetail(data.metaDetail); + } + }); + + }); + } + ); + function buildTree(data) { + // 构建 spanId 到节点的映射 + var nodeMap = new Map(); + data.forEach(function (item) { + nodeMap.set(item.logDTO.spanId, item); }); - } - function showRelatedDataInfluence(entityName, entityId, fieldName) { - $scope.entityNameOfFindRelated = entityName; - $scope.entityIdOfFindRelated = entityId; - $scope.fieldNameOfFindRelated = fieldName; + // 构建图的根节点列表 + var roots = []; + + data.forEach(function (item) { + var log = item.logDTO; + var parentSpanId = log.parentSpanId; + + if (parentSpanId && nodeMap.has(parentSpanId)) { + var parent = nodeMap.get(parentSpanId); + if (!parent.children) { + parent.children = []; + } + parent.children.push(item); + } else { + roots.push(item); + } + }); - if (entityId === 'AnyMatched') { - return; + // 递归生成 Treeview 格式的节点 + function buildTreeNode(node) { + var log = node.logDTO; + var treeNode = { + text: log.opName, + nodes: [], + metaDetail: node + }; + if (node.children) { + node.children.forEach(function (child) { + treeNode.nodes.push(buildTreeNode(child)); + }); + } + if (treeNode.nodes.length === 0) { + delete treeNode.nodes; + } + return treeNode; } - AuditLogService.find_dataInfluences_by_field( - $scope.entityNameOfFindRelated, - $scope.entityIdOfFindRelated, - $scope.fieldNameOfFindRelated, - $scope.relatedDataInfluencePage, - RelatedDataInfluencePageSize - ).then(function (result) { - if (!result || result.length < RelatedDataInfluencePageSize) { - $scope.relatedDataInfluenceHasLoadAll = true; - $scope.relatedDataInfluences = result; - return; - } - if (result.length === 0) { - return; - } - $scope.relatedDataInfluenceHasLoadAll = false; - $scope.relatedDataInfluences = result; - }); - } - - function findMoreRelatedDataInfluence() { - $scope.relatedDataInfluencePage = $scope.relatedDataInfluencePage + 1; - AuditLogService.find_dataInfluences_by_field( - $scope.entityNameOfFindRelated, - $scope.entityIdOfFindRelated, - $scope.fieldNameOfFindRelated, - $scope.relatedDataInfluencePage, - RelatedDataInfluencePageSize - ).then(function (result) { - if (!result || result.length < RelatedDataInfluencePageSize) { - $scope.relatedDataInfluenceHasLoadAll = true; - } - if (result.length === 0) { - return; - } - $scope.relatedDataInfluences = $scope.relatedDataInfluences.concat(result); - + return roots.map(function (root) { + return buildTreeNode(root); }); - } - - function findOpNameBySpanId(spanId) { - var res = ''; - $scope.traceDetails.forEach(function (detail) { - if (detail.logDTO.spanId === spanId) { - res = detail.logDTO.opName +'('+spanId.substr(0,5)+'...'+')'; - } - }); - return res; - } - - function refreshDataInfluenceEntities() { - var entityMap = new Map(); - $scope.showingDetail.dataInfluenceDTOList.forEach(function (dto) { - var key = { - name: dto.influenceEntityName, - id: dto.influenceEntityId - }; - var keyString = JSON.stringify(key); - var value = { - name: dto.influenceEntityName, - id: dto.influenceEntityId, - dtoList: [] - }; - if (!entityMap.has(keyString)) { - entityMap.set(keyString, value); - } - entityMap.get(keyString).dtoList.push(dto); - }); - $scope.dataInfluenceEntities = Array.from(entityMap); - } + } - function showText(text) { - $scope.text = text; - AppUtil.showModal("#showTextModal"); - } + function changeShowingDetail(data) { + $scope.showingDetail = data; + refreshDataInfluenceEntities(); + } + } + + function showRelatedDataInfluence(entityName, entityId, fieldName) { + $scope.entityNameOfFindRelated = entityName; + $scope.entityIdOfFindRelated = entityId; + $scope.fieldNameOfFindRelated = fieldName; + + if (entityId === 'AnyMatched') { + return; + } + + AuditLogService.find_dataInfluences_by_field( + $scope.entityNameOfFindRelated, + $scope.entityIdOfFindRelated, + $scope.fieldNameOfFindRelated, + $scope.relatedDataInfluencePage, + RelatedDataInfluencePageSize + ).then(function (result) { + if (!result || result.length < RelatedDataInfluencePageSize) { + $scope.relatedDataInfluenceHasLoadAll = true; + $scope.relatedDataInfluences = result; + return; + } + if (result.length === 0) { + return; + } + $scope.relatedDataInfluenceHasLoadAll = false; + $scope.relatedDataInfluences = result; + }); + } + + function findMoreRelatedDataInfluence() { + $scope.relatedDataInfluencePage = $scope.relatedDataInfluencePage + 1; + AuditLogService.find_dataInfluences_by_field( + $scope.entityNameOfFindRelated, + $scope.entityIdOfFindRelated, + $scope.fieldNameOfFindRelated, + $scope.relatedDataInfluencePage, + RelatedDataInfluencePageSize + ).then(function (result) { + if (!result || result.length < RelatedDataInfluencePageSize) { + $scope.relatedDataInfluenceHasLoadAll = true; + } + if (result.length === 0) { + return; + } + $scope.relatedDataInfluences = $scope.relatedDataInfluences.concat(result); + + }); + } + + function refreshDataInfluenceEntities() { + var entityMap = new Map(); + $scope.showingDetail.dataInfluenceDTOList.forEach(function (dto) { + var key = { + name: dto.influenceEntityName, + id: dto.influenceEntityId + }; + var keyString = JSON.stringify(key); + var value = { + name: dto.influenceEntityName, + id: dto.influenceEntityId, + dtoList: [] + }; + if (!entityMap.has(keyString)) { + entityMap.set(keyString, value); + } + entityMap.get(keyString).dtoList.push(dto); + }); + $scope.dataInfluenceEntities = Array.from(entityMap); + } + + function showText(text) { + $scope.text = text; + AppUtil.showModal("#showTextModal"); + } } \ No newline at end of file diff --git a/apollo-portal/src/main/resources/static/styles/audit-log.css b/apollo-portal/src/main/resources/static/styles/audit-log.css index a8363a00551..2dca5ab6da1 100644 --- a/apollo-portal/src/main/resources/static/styles/audit-log.css +++ b/apollo-portal/src/main/resources/static/styles/audit-log.css @@ -112,7 +112,7 @@ padding: 8px; margin-top: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .09); - border-radius: 3%; + border-radius: 0%; } .options-container { @@ -137,4 +137,30 @@ .options-list li:hover { background-color: #f0f0f0; +} + +.treeview { + background-color: #ffffff; + font-size: 14px; +} + +.node-treeview { + padding: 5px 0px; + transition: background-color 0.5s; + word-break: break-all; +} + +.node-treeview:last-child { + border-bottom: none; +} + +.node-treeview:hover { + background-color: #f0f0f0; /* 悬停时的背景颜色 */ +} + +#treeview .list-group .list-group-item { + border: 0; + border-top: 1px solid #eff2f7; + border-top-width: 0px; + color: #797979; } \ No newline at end of file

{{'ApolloAuditLog.DataInfluence.FieldNewValue' | translate }}