diff --git a/pom.xml b/pom.xml index 42a466b540..82a273d645 100755 --- a/pom.xml +++ b/pom.xml @@ -53,11 +53,12 @@ 1.6 UTF-8 3.8.0 + 2.22.1 3.0.1 3.0.1 2.8.2 1.6 - 0.8.1 + 0.8.2 3.1.0 @@ -163,6 +164,15 @@ ${java.encoding} + + org.apache.maven.plugins + maven-surefire-plugin + + + -Xms1024m -Xmx2048m + false + + org.jacoco jacoco-maven-plugin @@ -185,6 +195,11 @@ + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire.version} + org.apache.maven.plugins maven-jar-plugin diff --git a/sentinel-dashboard/src/main/java/com/taobao/csp/sentinel/dashboard/datasource/entity/rule/ParamFlowRuleEntity.java b/sentinel-dashboard/src/main/java/com/taobao/csp/sentinel/dashboard/datasource/entity/rule/ParamFlowRuleEntity.java index 44c221f795..fde8cfb410 100644 --- a/sentinel-dashboard/src/main/java/com/taobao/csp/sentinel/dashboard/datasource/entity/rule/ParamFlowRuleEntity.java +++ b/sentinel-dashboard/src/main/java/com/taobao/csp/sentinel/dashboard/datasource/entity/rule/ParamFlowRuleEntity.java @@ -55,7 +55,7 @@ public String getResource() { } @JsonIgnore - public int getBlockGrade() { + public int getGrade() { return rule.getGrade(); } diff --git a/sentinel-dashboard/src/main/java/com/taobao/csp/sentinel/dashboard/view/ParamFlowRuleController.java b/sentinel-dashboard/src/main/java/com/taobao/csp/sentinel/dashboard/view/ParamFlowRuleController.java index 0341d5c8de..7b897fdd95 100644 --- a/sentinel-dashboard/src/main/java/com/taobao/csp/sentinel/dashboard/view/ParamFlowRuleController.java +++ b/sentinel-dashboard/src/main/java/com/taobao/csp/sentinel/dashboard/view/ParamFlowRuleController.java @@ -165,7 +165,7 @@ private Result checkEntityInternal(ParamFlowRuleEntity entity) { if (entity.getCount() < 0) { return Result.ofFail(-1, "count should be valid"); } - if (entity.getBlockGrade() != RuleConstant.FLOW_GRADE_QPS) { + if (entity.getGrade() != RuleConstant.FLOW_GRADE_QPS) { return Result.ofFail(-1, "Unknown mode (blockGrade) for parameter flow control"); } if (entity.getParamIdx() == null || entity.getParamIdx() < 0) { diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/authority.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/authority.js index 1f190a76e1..96ef1239d2 100644 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/authority.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/authority.js @@ -94,24 +94,8 @@ angular.module('sentinelDashboardApp').controller('AuthorityRuleController', ['$ }); }; - function checkRuleValid(rule) { - if (rule.resource === undefined || rule.resource === '') { - alert('资源名称不能为空'); - return false; - } - if (rule.limitApp === undefined || rule.limitApp === '') { - alert('流控针对应用不能为空'); - return false; - } - if (rule.strategy === undefined) { - alert('必须选择黑白名单模式'); - return false; - } - return true; - } - $scope.saveRule = function () { - if (!checkRuleValid($scope.currentRule.rule)) { + if (!AuthorityRuleService.checkRuleValid($scope.currentRule.rule)) { return; } if ($scope.authorityRuleDialog.type === 'add') { @@ -136,7 +120,7 @@ angular.module('sentinelDashboardApp').controller('AuthorityRuleController', ['$ alert("添加规则失败:未知错误"); } }); - }; + } function saveRuleAndPush(rule, edit) { AuthorityRuleService.saveRule(rule).success(function (data) { diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js index 84a6823d60..0623c5035b 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/degrade.js @@ -81,33 +81,8 @@ app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDia }); }; - function checkRuleValid(rule) { - if (rule.resource === undefined || rule.resource === '') { - alert('资源名称不能为空'); - return false; - } - if (rule.grade === undefined || rule.grade < 0) { - alert('未知的降级类型'); - return false; - } - if (rule.count === undefined || rule.count === '' || rule.count < 0) { - alert('降级阈值不能为空或小于 0'); - return false; - } - if (rule.timeWindow === undefined || rule.timeWindow === '' || rule.timeWindow <= 0) { - alert('降级时间窗口必须大于 0'); - return false; - } - // 异常比率类型. - if (rule.grade == 1 && rule.count > 1) { - alert('异常比率超出范围:[0.0 - 1.0]'); - return false; - } - return true; - } - $scope.saveRule = function () { - if (!checkRuleValid($scope.currentRule)) { + if (!DegradeService.checkRuleValid($scope.currentRule)) { return; } if ($scope.degradeRuleDialog.type === 'add') { diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow.js index e24fcb0080..1c8a2fea55 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow.js @@ -88,50 +88,8 @@ app.controller('FlowCtl', ['$scope', '$stateParams', 'FlowService', 'ngDialog', }); }; - function notNumberAtLeastZero(num) { - return num === undefined || num === '' || isNaN(num) || num < 0; - } - - function notNumberGreaterThanZero(num) { - return num === undefined || num === '' || isNaN(num) || num <= 0; - } - - function checkRuleValid(rule) { - if (rule.resource === undefined || rule.resource === '') { - alert('资源名称不能为空'); - return false; - } - if (rule.count === undefined || rule.count < 0) { - alert('限流阈值必须大于等于 0'); - return false; - } - if (rule.strategy === undefined || rule.strategy < 0) { - alert('无效的流控模式'); - return false; - } - if (rule.strategy == 1 || rule.strategy == 2) { - if (rule.refResource === undefined || rule.refResource === '') { - alert('请填写关联资源或入口'); - return false; - } - } - if (rule.controlBehavior === undefined || rule.controlBehavior < 0) { - alert('无效的流控整形方式'); - return false; - } - if (rule.controlBehavior == 1 && notNumberGreaterThanZero(rule.warmUpPeriodSec)) { - alert('预热时长必须大于 0'); - return false; - } - if (rule.controlBehavior == 2 && notNumberGreaterThanZero(rule.maxQueueingTimeMs)) { - alert('排队超时时间必须大于 0'); - return false; - } - return true; - } - $scope.saveRule = function () { - if (!checkRuleValid($scope.currentRule)) { + if (!FlowService.checkRuleValid($scope.currentRule)) { return; } if ($scope.flowRuleDialog.type === 'add') { diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js index f464e0c298..e8b3a0d79c 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/identity.js @@ -1,18 +1,13 @@ var app = angular.module('sentinelDashboardApp'); app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', - 'ngDialog', 'FlowService', 'DegradeService', 'MachineService', + 'ngDialog', 'FlowService', 'DegradeService', 'AuthorityRuleService', 'ParamFlowService', 'MachineService', '$interval', '$location', '$timeout', function ($scope, $stateParams, IdentityService, ngDialog, - FlowService, DegradeService, MachineService, $interval, $location, $timeout) { + FlowService, DegradeService, AuthorityRuleService, ParamFlowService, MachineService, $interval, $location, $timeout) { $scope.app = $stateParams.app; - // $scope.rulesPageConfig = { - // pageSize : 10, - // currentPageIndex : 1, - // totalPage : 1, - // totalCount: 0, - // }; + $scope.currentPage = 1; $scope.pageSize = 16; $scope.totalPage = 1; @@ -90,10 +85,13 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', }; function saveFlowRule() { + if (!FlowService.checkRuleValid(flowRuleDialogScope.currentRule)) { + return; + } FlowService.newRule(flowRuleDialogScope.currentRule).success(function (data) { if (data.code == 0) { flowRuleDialog.close(); - var url = '/dashboard/flow/' + $scope.app; + let url = '/dashboard/flow/' + $scope.app; $location.path(url); } else { alert('失败!'); @@ -102,6 +100,9 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', } function saveFlowRuleAndContinue() { + if (!FlowService.checkRuleValid(flowRuleDialogScope.currentRule)) { + return; + } FlowService.newRule(flowRuleDialogScope.currentRule).success(function (data) { if (data.code == 0) { flowRuleDialog.close(); @@ -148,6 +149,9 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', }; function saveDegradeRule() { + if (!DegradeService.checkRuleValid(degradeRuleDialogScope.currentRule)) { + return; + } DegradeService.newRule(degradeRuleDialogScope.currentRule).success(function (data) { if (data.code == 0) { degradeRuleDialog.close(); @@ -160,6 +164,9 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', } function saveDegradeRuleAndContinue() { + if (!DegradeService.checkRuleValid(degradeRuleDialogScope.currentRule)) { + return; + } DegradeService.newRule(degradeRuleDialogScope.currentRule).success(function (data) { if (data.code == 0) { degradeRuleDialog.close(); @@ -169,9 +176,176 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', }); } + let authorityRuleDialog; + let authorityRuleDialogScope; + + function saveAuthorityRule() { + let ruleEntity = authorityRuleDialogScope.currentRule; + if (!AuthorityRuleService.checkRuleValid(ruleEntity.rule)) { + return; + } + AuthorityRuleService.addNewRule(ruleEntity).success((data) => { + if (data.success) { + authorityRuleDialog.close(); + let url = '/dashboard/authority/' + $scope.app; + $location.path(url); + } else { + alert('添加规则失败:' + data.msg); + } + }).error((data) => { + if (data) { + alert('添加规则失败:' + data.msg); + } else { + alert("添加规则失败:未知错误"); + } + }); + } + + function saveAuthorityRuleAndContinue() { + let ruleEntity = authorityRuleDialogScope.currentRule; + if (!AuthorityRuleService.checkRuleValid(ruleEntity.rule)) { + return; + } + AuthorityRuleService.addNewRule(ruleEntity).success((data) => { + if (data.success) { + authorityRuleDialog.close(); + } else { + alert('添加规则失败:' + data.msg); + } + }).error((data) => { + if (data) { + alert('添加规则失败:' + data.msg); + } else { + alert("添加规则失败:未知错误"); + } + }); + } + + $scope.addNewAuthorityRule = function (resource) { + if (!$scope.macInputModel) { + return; + } + let mac = $scope.macInputModel.split(':'); + authorityRuleDialogScope = $scope.$new(true); + authorityRuleDialogScope.currentRule = { + app: $scope.app, + ip: mac[0], + port: mac[1], + rule: { + resource: resource, + strategy: 0, + limitApp: '', + } + }; + + authorityRuleDialogScope.authorityRuleDialog = { + title: '新增授权规则', + type: 'add', + confirmBtnText: '新增', + saveAndContinueBtnText: '新增并继续添加' + }; + authorityRuleDialogScope.saveRule = saveAuthorityRule; + authorityRuleDialogScope.saveRuleAndContinue = saveAuthorityRuleAndContinue; + + authorityRuleDialog = ngDialog.open({ + template: '/app/views/dialog/authority-rule-dialog.html', + width: 680, + overlay: true, + scope: authorityRuleDialogScope + }); + }; + + let paramFlowRuleDialog; + let paramFlowRuleDialogScope; + + function saveParamFlowRule() { + let ruleEntity = paramFlowRuleDialogScope.currentRule; + if (!ParamFlowService.checkRuleValid(ruleEntity.rule)) { + return; + } + ParamFlowService.addNewRule(ruleEntity).success((data) => { + if (data.success) { + paramFlowRuleDialog.close(); + let url = '/dashboard/paramFlow/' + $scope.app; + $location.path(url); + } else { + alert('添加热点规则失败:' + data.msg); + } + }).error((data) => { + if (data) { + alert('添加热点规则失败:' + data.msg); + } else { + alert("添加热点规则失败:未知错误"); + } + }); + } + + function saveParamFlowRuleAndContinue() { + let ruleEntity = paramFlowRuleDialogScope.currentRule; + if (!ParamFlowService.checkRuleValid(ruleEntity.rule)) { + return; + } + ParamFlowService.addNewRule(ruleEntity).success((data) => { + if (data.success) { + paramFlowRuleDialog.close(); + } else { + alert('添加热点规则失败:' + data.msg); + } + }).error((data) => { + if (data) { + alert('添加热点规则失败:' + data.msg); + } else { + alert("添加热点规则失败:未知错误"); + } + }); + } + + $scope.addNewParamFlowRule = function (resource) { + if (!$scope.macInputModel) { + return; + } + let mac = $scope.macInputModel.split(':'); + paramFlowRuleDialogScope = $scope.$new(true); + paramFlowRuleDialogScope.currentRule = { + app: $scope.app, + ip: mac[0], + port: mac[1], + rule: { + resource: resource, + grade: 1, + paramFlowItemList: [], + count: 0, + limitApp: 'default', + } + }; + + paramFlowRuleDialogScope.paramFlowRuleDialog = { + title: '新增热点规则', + type: 'add', + confirmBtnText: '新增', + saveAndContinueBtnText: '新增并继续添加', + supportAdvanced: false, + showAdvanceButton: true + }; + paramFlowRuleDialogScope.saveRule = saveParamFlowRule; + paramFlowRuleDialogScope.saveRuleAndContinue = saveParamFlowRuleAndContinue; + // paramFlowRuleDialogScope.onOpenAdvanceClick = function () { + // paramFlowRuleDialogScope.paramFlowRuleDialog.showAdvanceButton = false; + // }; + // paramFlowRuleDialogScope.onCloseAdvanceClick = function () { + // paramFlowRuleDialogScope.paramFlowRuleDialog.showAdvanceButton = true; + // }; + + paramFlowRuleDialog = ngDialog.open({ + template: '/app/views/dialog/param-flow-rule-dialog.html', + width: 680, + overlay: true, + scope: paramFlowRuleDialogScope + }); + }; + var searchHandler; $scope.searchChange = function (searchKey) { - // console.info('searchKey=', searchKey); $timeout.cancel(searchHandler); searchHandler = $timeout(function () { $scope.searchKey = searchKey; @@ -180,14 +354,14 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', reInitIdentityDatas(); $scope.firstExpandAll = false; }, 600); - } + }; $scope.initTreeTable = function () { // if (!$scope.table) { com_github_culmat_jsTreeTable.register(window); $scope.table = window.treeTable($('#identities')); // } - } + }; $scope.expandAll = function () { $scope.isExpand = true; @@ -198,13 +372,12 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', $scope.treeView = function () { $scope.isTreeView = true; queryIdentities(); - } + }; $scope.listView = function () { $scope.isTreeView = false; queryIdentities(); - } + }; - queryAppMachines(); function queryAppMachines() { MachineService.getAppMachines($scope.app).success( function (data) { @@ -230,7 +403,10 @@ app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService', } } ); - }; + } + + // Fetch all machines by current app name. + queryAppMachines(); $scope.$watch('macInputModel', function () { if ($scope.macInputModel) { diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/param_flow.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/param_flow.js index e5441515d2..ebdbf6bde6 100644 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/param_flow.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/param_flow.js @@ -122,7 +122,7 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop .error((data, header, config, status) => { $scope.loadError = {message: "未知错误"} }); - }; + } $scope.getMachineRules = getMachineRules; getMachineRules(); @@ -134,6 +134,7 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop title: '编辑热点规则', type: 'edit', confirmBtnText: '保存', + supportAdvanced: true, showAdvanceButton: rule.rule.paramFlowItemList === undefined || rule.rule.paramFlowItemList.length <= 0 }; paramFlowRuleDialog = ngDialog.open({ @@ -152,7 +153,7 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop ip: mac[0], port: mac[1], rule: { - blockGrade: 1, + grade: 1, paramFlowItemList: [], count: 0, limitApp: 'default', @@ -180,38 +181,8 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop $scope.paramFlowRuleDialog.showAdvanceButton = true; }; - function checkRuleValid(rule) { - if (!rule.resource || rule.resource === '') { - alert('资源名称不能为空'); - return false; - } - if (rule.blockGrade !== 1) { - alert('未知的限流模式'); - return false; - } - if (rule.count < 0) { - alert('限流阈值必须大于等于 0'); - return false; - } - if (rule.paramIdx === undefined || rule.paramIdx === '' || isNaN(rule.paramIdx) || rule.paramIdx < 0) { - alert('热点参数索引必须大于等于 0'); - return false; - } - if (rule.paramFlowItemList !== undefined) { - for (let i = 0; i < rule.paramFlowItemList.length; i++) { - let item = rule.paramFlowItemList[i]; - if ($scope.notValidParamItem(item)) { - alert('热点参数例外项不合法,请检查值和类型是否正确:参数为 ' + item.object + ', 类型为 ' + - item.classType + ', 限流阈值为 ' + item.count); - return false; - } - } - } - return true; - } - $scope.saveRule = function () { - if (!checkRuleValid($scope.currentRule.rule)) { + if (!ParamFlowService.checkRuleValid($scope.currentRule.rule)) { return; } if ($scope.paramFlowRuleDialog.type === 'add') { @@ -236,7 +207,7 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop alert("添加规则失败:未知错误"); } }); - }; + } function saveRuleAndPush(rule, edit) { ParamFlowService.saveRule(rule).success(function (data) { @@ -290,7 +261,7 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop type: 'delete_rule', attentionTitle: '请确认是否删除如下热点参数限流规则', attention: '资源名: ' + ruleEntity.rule.resource + ', 热点参数索引: ' + ruleEntity.rule.paramIdx + - ', 限流模式: ' + (ruleEntity.rule.blockGrade === 1 ? 'QPS' : '未知') + ', 限流阈值: ' + ruleEntity.rule.count, + ', 限流模式: ' + (ruleEntity.rule.grade === 1 ? 'QPS' : '未知') + ', 限流阈值: ' + ruleEntity.rule.count, confirmBtnText: '删除', }; confirmDialog = ngDialog.open({ @@ -301,7 +272,7 @@ angular.module('sentinelDashboardApp').controller('ParamFlowController', ['$scop }; $scope.confirm = function () { - if ($scope.confirmDialog.type == 'delete_rule') { + if ($scope.confirmDialog.type === 'delete_rule') { deleteRuleAndPush($scope.currentRule); } else { console.error('error'); diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/authority_service.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/authority_service.js index 713e3e45a5..42a6101217 100644 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/authority_service.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/authority_service.js @@ -37,4 +37,20 @@ angular.module('sentinelDashboardApp').service('AuthorityRuleService', ['$http', method: 'DELETE' }); }; + + this.checkRuleValid = function checkRuleValid(rule) { + if (rule.resource === undefined || rule.resource === '') { + alert('资源名称不能为空'); + return false; + } + if (rule.limitApp === undefined || rule.limitApp === '') { + alert('流控针对应用不能为空'); + return false; + } + if (rule.strategy === undefined) { + alert('必须选择黑白名单模式'); + return false; + } + return true; + }; }]); diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/degradeservice.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/degradeservice.js index c4db2078b0..a708d5823d 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/degradeservice.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/degradeservice.js @@ -60,4 +60,29 @@ app.service('DegradeService', ['$http', function ($http) { method: 'GET' }); }; + + this.checkRuleValid = function (rule) { + if (rule.resource === undefined || rule.resource === '') { + alert('资源名称不能为空'); + return false; + } + if (rule.grade === undefined || rule.grade < 0) { + alert('未知的降级类型'); + return false; + } + if (rule.count === undefined || rule.count === '' || rule.count < 0) { + alert('降级阈值不能为空或小于 0'); + return false; + } + if (rule.timeWindow === undefined || rule.timeWindow === '' || rule.timeWindow <= 0) { + alert('降级时间窗口必须大于 0'); + return false; + } + // 异常比率类型. + if (rule.grade == 1 && rule.count > 1) { + alert('异常比率超出范围:[0.0 - 1.0]'); + return false; + } + return true; + }; }]); diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/flowservice.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/flowservice.js index 12fd6eac68..b089fe29cc 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/flowservice.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/flowservice.js @@ -70,4 +70,46 @@ app.service('FlowService', ['$http', function ($http) { method: 'GET' }); }; + + function notNumberAtLeastZero(num) { + return num === undefined || num === '' || isNaN(num) || num < 0; + } + + function notNumberGreaterThanZero(num) { + return num === undefined || num === '' || isNaN(num) || num <= 0; + } + + this.checkRuleValid = function (rule) { + if (rule.resource === undefined || rule.resource === '') { + alert('资源名称不能为空'); + return false; + } + if (rule.count === undefined || rule.count < 0) { + alert('限流阈值必须大于等于 0'); + return false; + } + if (rule.strategy === undefined || rule.strategy < 0) { + alert('无效的流控模式'); + return false; + } + if (rule.strategy == 1 || rule.strategy == 2) { + if (rule.refResource === undefined || rule.refResource == '') { + alert('请填写关联资源或入口'); + return false; + } + } + if (rule.controlBehavior === undefined || rule.controlBehavior < 0) { + alert('无效的流控整形方式'); + return false; + } + if (rule.controlBehavior == 1 && notNumberGreaterThanZero(rule.warmUpPeriodSec)) { + alert('预热时长必须大于 0'); + return false; + } + if (rule.controlBehavior == 2 && notNumberGreaterThanZero(rule.maxQueueingTimeMs)) { + alert('排队超时时间必须大于 0'); + return false; + } + return true; + }; }]); diff --git a/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/param_flow_service.js b/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/param_flow_service.js index aa09b58b28..2e2355546d 100644 --- a/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/param_flow_service.js +++ b/sentinel-dashboard/src/main/webapp/resources/app/scripts/services/param_flow_service.js @@ -39,4 +39,66 @@ angular.module('sentinelDashboardApp').service('ParamFlowService', ['$http', fun method: 'DELETE' }); }; + + function isNumberClass(classType) { + return classType === 'int' || classType === 'double' || + classType === 'float' || classType === 'long' || classType === 'short'; + } + + function isByteClass(classType) { + return classType === 'byte'; + } + + function notNumberAtLeastZero(num) { + return num === undefined || num === '' || isNaN(num) || num < 0; + } + + function notGoodNumber(num) { + return num === undefined || num === '' || isNaN(num); + } + + function notGoodNumberBetweenExclusive(num, l ,r) { + return num === undefined || num === '' || isNaN(num) || num < l || num > r; + } + + function notValidParamItem(curExItem) { + if (isNumberClass(curExItem.classType) && notGoodNumber(curExItem.object)) { + return true; + } + if (isByteClass(curExItem.classType) && notGoodNumberBetweenExclusive(curExItem.object, -128, 127)) { + return true; + } + return curExItem.object === undefined || curExItem.classType === undefined || + notNumberAtLeastZero(curExItem.count); + } + + this.checkRuleValid = function (rule) { + if (!rule.resource || rule.resource === '') { + alert('资源名称不能为空'); + return false; + } + if (rule.grade != 1) { + alert('未知的限流模式'); + return false; + } + if (rule.count < 0) { + alert('限流阈值必须大于等于 0'); + return false; + } + if (rule.paramIdx === undefined || rule.paramIdx === '' || isNaN(rule.paramIdx) || rule.paramIdx < 0) { + alert('热点参数索引必须大于等于 0'); + return false; + } + if (rule.paramFlowItemList !== undefined) { + for (var i = 0; i < rule.paramFlowItemList.length; i++) { + var item = rule.paramFlowItemList[i]; + if (notValidParamItem(item)) { + alert('热点参数例外项不合法,请检查值和类型是否正确:参数为 ' + item.object + ', 类型为 ' + + item.classType + ', 限流阈值为 ' + item.count); + return false; + } + } + } + return true; + }; }]); diff --git a/sentinel-dashboard/src/main/webapp/resources/app/views/dialog/param-flow-rule-dialog.html b/sentinel-dashboard/src/main/webapp/resources/app/views/dialog/param-flow-rule-dialog.html index 0e010bbf9c..8a15c4749a 100644 --- a/sentinel-dashboard/src/main/webapp/resources/app/views/dialog/param-flow-rule-dialog.html +++ b/sentinel-dashboard/src/main/webapp/resources/app/views/dialog/param-flow-rule-dialog.html @@ -101,7 +101,7 @@ -
+ diff --git a/sentinel-dashboard/src/main/webapp/resources/app/views/identity.html b/sentinel-dashboard/src/main/webapp/resources/app/views/identity.html index 03eba209bb..fc91ef6e77 100755 --- a/sentinel-dashboard/src/main/webapp/resources/app/views/identity.html +++ b/sentinel-dashboard/src/main/webapp/resources/app/views/identity.html @@ -41,13 +41,13 @@ 资源名 - 通过QPS - 拒绝QPS - 线程数 - 平均RT - 分钟通过 - 分钟拒绝 - 操作 + 通过QPS + 拒绝QPS + 线程数 + 平均RT + 分钟通过 + 分钟拒绝 + 操作 @@ -74,6 +74,10 @@  流控 + +
diff --git a/sentinel-dashboard/src/main/webapp/resources/dist/js/app.js b/sentinel-dashboard/src/main/webapp/resources/dist/js/app.js old mode 100755 new mode 100644 index cf2620c134..632616f24b --- a/sentinel-dashboard/src/main/webapp/resources/dist/js/app.js +++ b/sentinel-dashboard/src/main/webapp/resources/dist/js/app.js @@ -1 +1 @@ -"use strict";var app;angular.module("sentinelDashboardApp",["oc.lazyLoad","ui.router","ui.bootstrap","angular-loading-bar","ngDialog","ui.bootstrap.datetimepicker","ui-notification","rzTable","angular-clipboard","selectize","angularUtils.directives.dirPagination"]).config(["$stateProvider","$urlRouterProvider","$ocLazyLoadProvider",function(e,r,a){a.config({debug:!1,events:!0}),r.otherwise("/dashboard/home"),e.state("dashboard",{url:"/dashboard",templateUrl:"app/views/dashboard/main.html",resolve:{loadMyDirectives:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/directives/header/header.js","app/scripts/directives/sidebar/sidebar.js","app/scripts/directives/sidebar/sidebar-search/sidebar-search.js"]})}]}}).state("dashboard.home",{url:"/home",templateUrl:"app/views/dashboard/home.html",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/main.js"]})}]}}).state("dashboard.flow",{templateUrl:"app/views/flow.html",url:"/flow/:app",controller:"FlowCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/flow.js"]})}]}}).state("dashboard.paramFlow",{templateUrl:"app/views/param_flow.html",url:"/paramFlow/:app",controller:"ParamFlowController",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/param_flow.js"]})}]}}).state("dashboard.authority",{templateUrl:"app/views/authority.html",url:"/authority/:app",controller:"AuthorityRuleController",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/authority.js"]})}]}}).state("dashboard.degrade",{templateUrl:"app/views/degrade.html",url:"/degrade/:app",controller:"DegradeCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/degrade.js"]})}]}}).state("dashboard.system",{templateUrl:"app/views/system.html",url:"/system/:app",controller:"SystemCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/system.js"]})}]}}).state("dashboard.machine",{templateUrl:"app/views/machine.html",url:"/app/:app",controller:"MachineCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/machine.js"]})}]}}).state("dashboard.identity",{templateUrl:"app/views/identity.html",url:"/identity/:app",controller:"IdentityCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/identity.js"]})}]}}).state("dashboard.metric",{templateUrl:"app/views/metric.html",url:"/metric/:app",controller:"MetricCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/metric.js"]})}]}})}]),(app=angular.module("sentinelDashboardApp")).filter("range",[function(){return function(e,r){if(isNaN(r)||r<=0)return[];e=[];for(var a=1;a<=r;a++)e.push(a);return e}}]),(app=angular.module("sentinelDashboardApp")).service("AppService",["$http",function(e){this.getApps=function(){return e({url:"app/briefinfos.json",method:"GET"})}}]),(app=angular.module("sentinelDashboardApp")).service("FlowService",["$http",function(t){this.queryMachineRules=function(e,r,a){return t({url:"flow/rules.json",params:{app:e,ip:r,port:a},method:"GET"})},this.newRule=function(e){var r={resource:e.resource,limitApp:e.limitApp,grade:e.grade,count:e.count,strategy:e.strategy,refResource:e.refResource,controlBehavior:e.controlBehavior,warmUpPeriodSec:e.warmUpPeriodSec,maxQueueingTimeMs:e.maxQueueingTimeMs,app:e.app,ip:e.ip,port:e.port};return t({url:"/flow/new.json",params:r,method:"GET"})},this.saveRule=function(e){var r={id:e.id,resource:e.resource,limitApp:e.limitApp,grade:e.grade,count:e.count,strategy:e.strategy,refResource:e.refResource,controlBehavior:e.controlBehavior,warmUpPeriodSec:e.warmUpPeriodSec,maxQueueingTimeMs:e.maxQueueingTimeMs};return t({url:"/flow/save.json",params:r,method:"GET"})},this.deleteRule=function(e){var r={id:e.id,app:e.app};return t({url:"/flow/delete.json",params:r,method:"GET"})}}]),(app=angular.module("sentinelDashboardApp")).service("DegradeService",["$http",function(t){this.queryMachineRules=function(e,r,a){return t({url:"degrade/rules.json",params:{app:e,ip:r,port:a},method:"GET"})},this.newRule=function(e){var r={id:e.id,resource:e.resource,limitApp:e.limitApp,count:e.count,timeWindow:e.timeWindow,grade:e.grade,app:e.app,ip:e.ip,port:e.port};return t({url:"/degrade/new.json",params:r,method:"GET"})},this.saveRule=function(e){var r={id:e.id,resource:e.resource,limitApp:e.limitApp,grade:e.grade,count:e.count,timeWindow:e.timeWindow};return t({url:"/degrade/save.json",params:r,method:"GET"})},this.deleteRule=function(e){var r={id:e.id,app:e.app};return t({url:"/degrade/delete.json",params:r,method:"GET"})}}]),(app=angular.module("sentinelDashboardApp")).service("SystemService",["$http",function(t){this.queryMachineRules=function(e,r,a){return t({url:"system/rules.json",params:{app:e,ip:r,port:a},method:"GET"})},this.newRule=function(e){var r={app:e.app,ip:e.ip,port:e.port};return 0==e.grade?r.avgLoad=e.avgLoad:1==e.grade?r.avgRt=e.avgRt:2==e.grade?r.maxThread=e.maxThread:3==e.grade&&(r.qps=e.qps),t({url:"/system/new.json",params:r,method:"GET"})},this.saveRule=function(e){var r={id:e.id};return 0==e.grade?r.avgLoad=e.avgLoad:1==e.grade?r.avgRt=e.avgRt:2==e.grade?r.maxThread=e.maxThread:3==e.grade&&(r.qps=e.qps),t({url:"/system/save.json",params:r,method:"GET"})},this.deleteRule=function(e){var r={id:e.id,app:e.app};return t({url:"/system/delete.json",params:r,method:"GET"})}}]),(app=angular.module("sentinelDashboardApp")).service("MachineService",["$http",function(r){this.getAppMachines=function(e){return r({url:"app/"+e+"/machines.json",method:"GET"})}}]),(app=angular.module("sentinelDashboardApp")).service("IdentityService",["$http",function(t){this.fetchIdentityOfMachine=function(e,r,a){return t({url:"resource/machineResource.json",params:{ip:e,port:r,searchKey:a},method:"GET"})},this.fetchClusterNodeOfMachine=function(e,r,a){return t({url:"resource/machineResource.json",params:{ip:e,port:r,type:"cluster",searchKey:a},method:"GET"})}}]),(app=angular.module("sentinelDashboardApp")).service("MetricService",["$http",function(s){this.queryAppSortedIdentities=function(e){return s({url:"/metric/queryTopResourceMetric.json",params:e,method:"GET"})},this.queryByAppAndIdentity=function(e){return s({url:"/metric/queryByAppAndResource.json",params:e,method:"GET"})},this.queryByMachineAndIdentity=function(e,r,a,t,o){var i={ip:e,port:r,identity:a,startTime:t.getTime(),endTime:o.getTime()};return s({url:"/metric/queryByAppAndResource.json",params:i,method:"GET"})}}]),angular.module("sentinelDashboardApp").service("ParamFlowService",["$http",function(t){this.queryMachineRules=function(e,r,a){return t({url:"/paramFlow/rules",params:{app:e,ip:r,port:a},method:"GET"})},this.addNewRule=function(e){return t({url:"/paramFlow/rule",data:e,method:"POST"})},this.saveRule=function(e){return t({url:"/paramFlow/rule/"+e.id,data:e,method:"PUT"})},this.deleteRule=function(e){return t({url:"/paramFlow/rule/"+e.id,method:"DELETE"})}}]),angular.module("sentinelDashboardApp").service("AuthorityRuleService",["$http",function(t){this.queryMachineRules=function(e,r,a){return t({url:"/authority/rules",params:{app:e,ip:r,port:a},method:"GET"})},this.addNewRule=function(e){return t({url:"/authority/rule",data:e,method:"POST"})},this.saveRule=function(e){return t({url:"/authority/rule/"+e.id,data:e,method:"PUT"})},this.deleteRule=function(e){return t({url:"/authority/rule/"+e.id,method:"DELETE"})}}]); \ No newline at end of file +"use strict";var app;angular.module("sentinelDashboardApp",["oc.lazyLoad","ui.router","ui.bootstrap","angular-loading-bar","ngDialog","ui.bootstrap.datetimepicker","ui-notification","rzTable","angular-clipboard","selectize","angularUtils.directives.dirPagination"]).config(["$stateProvider","$urlRouterProvider","$ocLazyLoadProvider",function(e,r,t){t.config({debug:!1,events:!0}),r.otherwise("/dashboard/home"),e.state("dashboard",{url:"/dashboard",templateUrl:"app/views/dashboard/main.html",resolve:{loadMyDirectives:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/directives/header/header.js","app/scripts/directives/sidebar/sidebar.js","app/scripts/directives/sidebar/sidebar-search/sidebar-search.js"]})}]}}).state("dashboard.home",{url:"/home",templateUrl:"app/views/dashboard/home.html",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/main.js"]})}]}}).state("dashboard.flow",{templateUrl:"app/views/flow.html",url:"/flow/:app",controller:"FlowCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/flow.js"]})}]}}).state("dashboard.paramFlow",{templateUrl:"app/views/param_flow.html",url:"/paramFlow/:app",controller:"ParamFlowController",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/param_flow.js"]})}]}}).state("dashboard.authority",{templateUrl:"app/views/authority.html",url:"/authority/:app",controller:"AuthorityRuleController",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/authority.js"]})}]}}).state("dashboard.degrade",{templateUrl:"app/views/degrade.html",url:"/degrade/:app",controller:"DegradeCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/degrade.js"]})}]}}).state("dashboard.system",{templateUrl:"app/views/system.html",url:"/system/:app",controller:"SystemCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/system.js"]})}]}}).state("dashboard.machine",{templateUrl:"app/views/machine.html",url:"/app/:app",controller:"MachineCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/machine.js"]})}]}}).state("dashboard.identity",{templateUrl:"app/views/identity.html",url:"/identity/:app",controller:"IdentityCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/identity.js"]})}]}}).state("dashboard.metric",{templateUrl:"app/views/metric.html",url:"/metric/:app",controller:"MetricCtl",resolve:{loadMyFiles:["$ocLazyLoad",function(e){return e.load({name:"sentinelDashboardApp",files:["app/scripts/controllers/metric.js"]})}]}})}]),(app=angular.module("sentinelDashboardApp")).filter("range",[function(){return function(e,r){if(isNaN(r)||r<=0)return[];e=[];for(var t=1;t<=r;t++)e.push(t);return e}}]),(app=angular.module("sentinelDashboardApp")).service("AppService",["$http",function(e){this.getApps=function(){return e({url:"app/briefinfos.json",method:"GET"})}}]),(app=angular.module("sentinelDashboardApp")).service("FlowService",["$http",function(a){function r(e){return void 0===e||""===e||isNaN(e)||e<=0}this.queryMachineRules=function(e,r,t){return a({url:"flow/rules.json",params:{app:e,ip:r,port:t},method:"GET"})},this.newRule=function(e){var r={resource:e.resource,limitApp:e.limitApp,grade:e.grade,count:e.count,strategy:e.strategy,refResource:e.refResource,controlBehavior:e.controlBehavior,warmUpPeriodSec:e.warmUpPeriodSec,maxQueueingTimeMs:e.maxQueueingTimeMs,app:e.app,ip:e.ip,port:e.port};return a({url:"/flow/new.json",params:r,method:"GET"})},this.saveRule=function(e){var r={id:e.id,resource:e.resource,limitApp:e.limitApp,grade:e.grade,count:e.count,strategy:e.strategy,refResource:e.refResource,controlBehavior:e.controlBehavior,warmUpPeriodSec:e.warmUpPeriodSec,maxQueueingTimeMs:e.maxQueueingTimeMs};return a({url:"/flow/save.json",params:r,method:"GET"})},this.deleteRule=function(e){var r={id:e.id,app:e.app};return a({url:"/flow/delete.json",params:r,method:"GET"})},this.checkRuleValid=function(e){return void 0===e.resource||""===e.resource?(alert("资源名称不能为空"),!1):void 0===e.count||e.count<0?(alert("限流阈值必须大于等于 0"),!1):void 0===e.strategy||e.strategy<0?(alert("无效的流控模式"),!1):1!=e.strategy&&2!=e.strategy||void 0!==e.refResource&&""!=e.refResource?void 0===e.controlBehavior||e.controlBehavior<0?(alert("无效的流控整形方式"),!1):1==e.controlBehavior&&r(e.warmUpPeriodSec)?(alert("预热时长必须大于 0"),!1):2!=e.controlBehavior||!r(e.maxQueueingTimeMs)||(alert("排队超时时间必须大于 0"),!1):(alert("请填写关联资源或入口"),!1)}}]),(app=angular.module("sentinelDashboardApp")).service("DegradeService",["$http",function(a){this.queryMachineRules=function(e,r,t){return a({url:"degrade/rules.json",params:{app:e,ip:r,port:t},method:"GET"})},this.newRule=function(e){var r={id:e.id,resource:e.resource,limitApp:e.limitApp,count:e.count,timeWindow:e.timeWindow,grade:e.grade,app:e.app,ip:e.ip,port:e.port};return a({url:"/degrade/new.json",params:r,method:"GET"})},this.saveRule=function(e){var r={id:e.id,resource:e.resource,limitApp:e.limitApp,grade:e.grade,count:e.count,timeWindow:e.timeWindow};return a({url:"/degrade/save.json",params:r,method:"GET"})},this.deleteRule=function(e){var r={id:e.id,app:e.app};return a({url:"/degrade/delete.json",params:r,method:"GET"})},this.checkRuleValid=function(e){return void 0===e.resource||""===e.resource?(alert("资源名称不能为空"),!1):void 0===e.grade||e.grade<0?(alert("未知的降级类型"),!1):void 0===e.count||""===e.count||e.count<0?(alert("降级阈值不能为空或小于 0"),!1):void 0===e.timeWindow||""===e.timeWindow||e.timeWindow<=0?(alert("降级时间窗口必须大于 0"),!1):!(1==e.grade&&1