diff --git a/internal/web/actions/default/clusters/cluster/boards/index.go b/internal/web/actions/default/clusters/cluster/boards/index.go index 7b572016..dacb363c 100644 --- a/internal/web/actions/default/clusters/cluster/boards/index.go +++ b/internal/web/actions/default/clusters/cluster/boards/index.go @@ -50,6 +50,8 @@ func (this *IndexAction) RunGet(params struct { "cachedBytes": stat.CachedBytes, "countRequests": stat.CountRequests, "countCachedRequests": stat.CountCachedRequests, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, "day": stat.Hour[4:6] + "月" + stat.Hour[6:8] + "日", "hour": stat.Hour[8:], }) @@ -66,6 +68,8 @@ func (this *IndexAction) RunGet(params struct { "cachedBytes": stat.CachedBytes, "countRequests": stat.CountRequests, "countCachedRequests": stat.CountCachedRequests, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, "day": stat.Day[4:6] + "月" + stat.Day[6:] + "日", }) } diff --git a/internal/web/actions/default/clusters/cluster/node/boards/index.go b/internal/web/actions/default/clusters/cluster/node/boards/index.go index e52ed4da..d3154e1a 100644 --- a/internal/web/actions/default/clusters/cluster/node/boards/index.go +++ b/internal/web/actions/default/clusters/cluster/node/boards/index.go @@ -69,6 +69,8 @@ func (this *IndexAction) RunGet(params struct { "cachedBytes": stat.CachedBytes, "countRequests": stat.CountRequests, "countCachedRequests": stat.CountCachedRequests, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, "day": stat.Hour[4:6] + "月" + stat.Hour[6:8] + "日", "hour": stat.Hour[8:], }) @@ -85,6 +87,8 @@ func (this *IndexAction) RunGet(params struct { "cachedBytes": stat.CachedBytes, "countRequests": stat.CountRequests, "countCachedRequests": stat.CountCachedRequests, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, "day": stat.Day[4:6] + "月" + stat.Day[6:] + "日", }) } diff --git a/internal/web/actions/default/dashboard/boards/index.go b/internal/web/actions/default/dashboard/boards/index.go index 94c36d6a..63575fab 100644 --- a/internal/web/actions/default/dashboard/boards/index.go +++ b/internal/web/actions/default/dashboard/boards/index.go @@ -80,8 +80,14 @@ func (this *IndexAction) RunGet(params struct{}) { statMaps := []maps.Map{} for _, stat := range resp.HourlyTrafficStats { statMaps = append(statMaps, maps.Map{ - "bytes": stat.Bytes, - "hour": stat.Hour[8:], + "bytes": stat.Bytes, + "cachedBytes": stat.CachedBytes, + "countRequests": stat.CountRequests, + "countCachedRequests": stat.CountCachedRequests, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, + "day": stat.Hour[4:6] + "月" + stat.Hour[6:8] + "日", + "hour": stat.Hour[8:], }) } this.Data["hourlyTrafficStats"] = statMaps @@ -92,13 +98,46 @@ func (this *IndexAction) RunGet(params struct{}) { statMaps := []maps.Map{} for _, stat := range resp.DailyTrafficStats { statMaps = append(statMaps, maps.Map{ - "bytes": stat.Bytes, - "day": stat.Day[4:6] + "月" + stat.Day[6:] + "日", + "bytes": stat.Bytes, + "cachedBytes": stat.CachedBytes, + "countRequests": stat.CountRequests, + "countCachedRequests": stat.CountCachedRequests, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, + "day": stat.Day[4:6] + "月" + stat.Day[6:] + "日", }) } this.Data["dailyTrafficStats"] = statMaps } + // 节点排行 + { + var statMaps = []maps.Map{} + for _, stat := range resp.TopNodeStats { + statMaps = append(statMaps, maps.Map{ + "nodeId": stat.NodeId, + "nodeName": stat.NodeName, + "countRequests": stat.CountRequests, + "bytes": stat.Bytes, + }) + } + this.Data["topNodeStats"] = statMaps + } + + // 域名排行 + { + var statMaps = []maps.Map{} + for _, stat := range resp.TopDomainStats { + statMaps = append(statMaps, maps.Map{ + "serverId": stat.ServerId, + "domain": stat.Domain, + "countRequests": stat.CountRequests, + "bytes": stat.Bytes, + }) + } + this.Data["topDomainStats"] = statMaps + } + // 版本升级 if resp.NodeUpgradeInfo != nil { this.Data["nodeUpgradeInfo"] = maps.Map{ diff --git a/internal/web/actions/default/servers/server/boards/index.go b/internal/web/actions/default/servers/server/boards/index.go index b94d759d..d983d3ac 100644 --- a/internal/web/actions/default/servers/server/boards/index.go +++ b/internal/web/actions/default/servers/server/boards/index.go @@ -26,6 +26,21 @@ func (this *IndexAction) RunGet(params struct { return } + serverResp, err := this.RPC().ServerRPC().FindEnabledServer(this.AdminContext(), &pb.FindEnabledServerRequest{ServerId: params.ServerId}) + if err != nil { + this.ErrorPage(err) + return + } + var server = serverResp.Server + if server == nil { + this.NotFound("server", params.ServerId) + return + } + this.Data["server"] = maps.Map{ + "id": server.Id, + "name": server.Name, + } + resp, err := this.RPC().ServerStatBoardRPC().ComposeServerStatBoard(this.AdminContext(), &pb.ComposeServerStatBoardRequest{ServerId: params.ServerId}) if err != nil { this.ErrorPage(err) @@ -41,6 +56,8 @@ func (this *IndexAction) RunGet(params struct { "cachedBytes": stat.CachedBytes, "countRequests": stat.CountRequests, "countCachedRequests": stat.CountCachedRequests, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, "day": stat.Hour[4:6] + "月" + stat.Hour[6:8] + "日", "hour": stat.Hour[8:], }) @@ -57,6 +74,8 @@ func (this *IndexAction) RunGet(params struct { "cachedBytes": stat.CachedBytes, "countRequests": stat.CountRequests, "countCachedRequests": stat.CountCachedRequests, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, "day": stat.Day[4:6] + "月" + stat.Day[6:] + "日", }) } @@ -68,10 +87,12 @@ func (this *IndexAction) RunGet(params struct { var statMaps = []maps.Map{} for _, stat := range resp.TopNodeStats { statMaps = append(statMaps, maps.Map{ - "nodeId": stat.NodeId, - "nodeName": stat.NodeName, - "countRequests": stat.CountRequests, - "bytes": stat.Bytes, + "nodeId": stat.NodeId, + "nodeName": stat.NodeName, + "countRequests": stat.CountRequests, + "bytes": stat.Bytes, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, }) } this.Data["topNodeStats"] = statMaps @@ -82,10 +103,12 @@ func (this *IndexAction) RunGet(params struct { var statMaps = []maps.Map{} for _, stat := range resp.TopDomainStats { statMaps = append(statMaps, maps.Map{ - "serverId": stat.ServerId, - "domain": stat.Domain, - "countRequests": stat.CountRequests, - "bytes": stat.Bytes, + "serverId": stat.ServerId, + "domain": stat.Domain, + "countRequests": stat.CountRequests, + "bytes": stat.Bytes, + "countAttackRequests": stat.CountAttackRequests, + "attackBytes": stat.AttackBytes, }) } this.Data["topDomainStats"] = statMaps diff --git a/web/views/@default/clusters/cluster/boards/index.js b/web/views/@default/clusters/cluster/boards/index.js index 4f963500..b1d97963 100644 --- a/web/views/@default/clusters/cluster/boards/index.js +++ b/web/views/@default/clusters/cluster/boards/index.js @@ -28,34 +28,30 @@ Tea.context(function () { this.reloadHourlyTrafficChart = function () { let stats = this.hourlyStats this.reloadTrafficChart("hourly-traffic-chart", "流量统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 流量: " + teaweb.formatBytes(stats[args.dataIndex].bytes) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].bytes > 0) { + cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100 + attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].bytes > 0) { - ratio = Math.round(stats[args.dataIndex].cachedBytes * 10000 / stats[args.dataIndex].bytes) / 100 - } - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 缓存流量: " + teaweb.formatBytes(stats[args.dataIndex].cachedBytes) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + " " + stats[index].hour + "时总流量:" + teaweb.formatBytes(stats[index].bytes) + "缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "缓存命中率:" + cachedRatio + "%拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "拦截比例:" + attackRatio + "%" }) } this.reloadDailyTrafficChart = function () { let stats = this.dailyStats this.reloadTrafficChart("daily-traffic-chart", "流量统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " 流量: " + teaweb.formatBytes(stats[args.dataIndex].bytes) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].bytes > 0) { + cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100 + attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].bytes > 0) { - ratio = Math.round(stats[args.dataIndex].cachedBytes * 10000 / stats[args.dataIndex].bytes) / 100 - } - return stats[args.dataIndex].day + " 缓存流量: " + teaweb.formatBytes(stats[args.dataIndex].cachedBytes) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + "总流量:" + teaweb.formatBytes(stats[index].bytes) + "缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "缓存命中率:" + cachedRatio + "%拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "拦截比例:" + attackRatio + "%" }) } @@ -123,10 +119,20 @@ Tea.context(function () { areaStyle: { color: "#61A0A8" } + }, + { + name: "攻击流量", + type: "line", + data: stats.map(function (v) { + return v.attackBytes / axis.divider + }), + itemStyle: { + color: "#F39494" + } } ], legend: { - data: ['流量', '缓存流量'] + data: ["流量", "缓存流量", "攻击流量"] }, animation: true } @@ -155,34 +161,30 @@ Tea.context(function () { this.reloadHourlyRequestsChart = function () { let stats = this.hourlyStats this.reloadRequestsChart("hourly-requests-chart", "请求数统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 请求数: " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].countRequests > 0) { + cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100 + attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].countRequests > 0) { - ratio = Math.round(stats[args.dataIndex].countCachedRequests * 10000 / stats[args.dataIndex].countRequests) / 100 - } - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 缓存请求数: " + teaweb.formatNumber(stats[args.dataIndex].countCachedRequests) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + " " + stats[index].hour + "时总请求数:" + stats[index].countRequests + "缓存请求数:" + stats[index].countCachedRequests + "缓存命中率:" + cachedRatio + "%拦截攻击数:" + stats[index].countAttackRequests + "拦截比例:" + attackRatio + "%" }) } this.reloadDailyRequestsChart = function () { let stats = this.dailyStats this.reloadRequestsChart("daily-requests-chart", "请求数统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " 请求数: " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].countRequests > 0) { + cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100 + attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].countRequests > 0) { - ratio = Math.round(stats[args.dataIndex].countCachedRequests * 10000 / stats[args.dataIndex].countRequests) / 100 - } - return stats[args.dataIndex].day + " 缓存请求数: " + teaweb.formatNumber(stats[args.dataIndex].countCachedRequests) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + "总请求数:" + stats[index].countRequests + "缓存请求数:" + stats[index].countCachedRequests + "缓存命中率:" + cachedRatio + "%拦截攻击数:" + stats[index].countAttackRequests + "拦截比例:" + attackRatio + "%" }) } @@ -253,10 +255,23 @@ Tea.context(function () { areaStyle: { color: "#61A0A8" } + }, + { + name: "攻击请求数", + type: "line", + data: stats.map(function (v) { + return v.countAttackRequests / axis.divider; + }), + itemStyle: { + color: "#F39494" + }, + lineStyle: { + color: "#F39494" + } } ], legend: { - data: ['请求数', '缓存请求数'] + data: ["请求数", "缓存请求数", "攻击请求数"] }, animation: true } diff --git a/web/views/@default/clusters/cluster/node/@node_menu.html b/web/views/@default/clusters/cluster/node/@node_menu.html index 2131f68b..5be7aee6 100644 --- a/web/views/@default/clusters/cluster/node/@node_menu.html +++ b/web/views/@default/clusters/cluster/node/@node_menu.html @@ -1,6 +1,6 @@ 节点列表 - | + | "{{node.name}}"节点详情 "{{node.name}}" 节点看板 diff --git a/web/views/@default/clusters/cluster/node/boards/index.js b/web/views/@default/clusters/cluster/node/boards/index.js index 238d9a6f..2774ca6b 100644 --- a/web/views/@default/clusters/cluster/node/boards/index.js +++ b/web/views/@default/clusters/cluster/node/boards/index.js @@ -74,34 +74,30 @@ Tea.context(function () { this.reloadHourlyTrafficChart = function () { let stats = this.hourlyStats this.reloadTrafficChart("hourly-traffic-chart", "流量统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 流量: " + teaweb.formatBytes(stats[args.dataIndex].bytes) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].bytes > 0) { + cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100 + attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].bytes > 0) { - ratio = Math.round(stats[args.dataIndex].cachedBytes * 10000 / stats[args.dataIndex].bytes) / 100 - } - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 缓存流量: " + teaweb.formatBytes(stats[args.dataIndex].cachedBytes) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + " " + stats[index].hour + "时总流量:" + teaweb.formatBytes(stats[index].bytes) + "缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "缓存命中率:" + cachedRatio + "%拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "拦截比例:" + attackRatio + "%" }) } this.reloadDailyTrafficChart = function () { let stats = this.dailyStats this.reloadTrafficChart("daily-traffic-chart", "流量统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " 流量: " + teaweb.formatBytes(stats[args.dataIndex].bytes) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].bytes > 0) { + cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100 + attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].bytes > 0) { - ratio = Math.round(stats[args.dataIndex].cachedBytes * 10000 / stats[args.dataIndex].bytes) / 100 - } - return stats[args.dataIndex].day + " 缓存流量: " + teaweb.formatBytes(stats[args.dataIndex].cachedBytes) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + "总流量:" + teaweb.formatBytes(stats[index].bytes) + "缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "缓存命中率:" + cachedRatio + "%拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "拦截比例:" + attackRatio + "%" }) } @@ -169,10 +165,23 @@ Tea.context(function () { areaStyle: { color: "#61A0A8" } + }, + { + name: "攻击流量", + type: "line", + data: stats.map(function (v) { + return v.attackBytes / axis.divider; + }), + itemStyle: { + color: "#F39494" + }, + lineStyle: { + color: "#F39494" + } } ], legend: { - data: ['流量', '缓存流量'] + data: ["流量", "缓存流量", "攻击流量"] }, animation: true } @@ -201,34 +210,30 @@ Tea.context(function () { this.reloadHourlyRequestsChart = function () { let stats = this.hourlyStats this.reloadRequestsChart("hourly-requests-chart", "请求数统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 请求数: " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].countRequests > 0) { + cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100 + attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].countRequests > 0) { - ratio = Math.round(stats[args.dataIndex].countCachedRequests * 10000 / stats[args.dataIndex].countRequests) / 100 - } - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 缓存请求数: " + teaweb.formatNumber(stats[args.dataIndex].countCachedRequests) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + " " + stats[index].hour + "时总请求数:" + stats[index].countRequests + "缓存请求数:" + stats[index].countCachedRequests + "缓存命中率:" + cachedRatio + "%拦截攻击数:" + stats[index].countAttackRequests + "拦截比例:" + attackRatio + "%" }) } this.reloadDailyRequestsChart = function () { let stats = this.dailyStats this.reloadRequestsChart("daily-requests-chart", "请求数统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " 请求数: " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].countRequests > 0) { + cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100 + attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].countRequests > 0) { - ratio = Math.round(stats[args.dataIndex].countCachedRequests * 10000 / stats[args.dataIndex].countRequests) / 100 - } - return stats[args.dataIndex].day + " 缓存请求数: " + teaweb.formatNumber(stats[args.dataIndex].countCachedRequests) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + "总请求数:" + stats[index].countRequests + "缓存请求数:" + stats[index].countCachedRequests + "缓存命中率:" + cachedRatio + "%拦截攻击数:" + stats[index].countAttackRequests + "拦截比例:" + attackRatio + "%" }) } @@ -299,10 +304,23 @@ Tea.context(function () { areaStyle: { color: "#61A0A8" } + }, + { + name: "攻击请求数", + type: "line", + data: stats.map(function (v) { + return v.countAttackRequests / axis.divider; + }), + itemStyle: { + color: "#F39494" + }, + lineStyle: { + color: "#F39494" + } } ], legend: { - data: ['请求数', '缓存请求数'] + data: ["请求数", "缓存请求数", "攻击请求数"] }, animation: true } @@ -328,7 +346,10 @@ Tea.context(function () { value: function (v) { return v.countRequests / axis.divider; }, - axis: axis + axis: axis, + click: function (args, stats) { + window.location = "/servers/server?serverId=" + stats[args.dataIndex].serverId + } }) } @@ -450,6 +471,9 @@ Tea.context(function () { return stats[args.dataIndex].time + "使用:" + teaweb.formatBytes(v.used) + "总量:" + teaweb.formatBytes(v.total) + "比例:" + (Math.ceil(v.used * 100 / v.total * 100) / 100) + "%" }, value: function (v) { + if (v.value.dirs.length ==0) { + return 0 + } v = v.value.dirs[0] return (v.used * 100 / v.total); }, diff --git a/web/views/@default/dashboard/boards/index.html b/web/views/@default/dashboard/boards/index.html index 1df7eb65..2436abff 100644 --- a/web/views/@default/dashboard/boards/index.html +++ b/web/views/@default/dashboard/boards/index.html @@ -2,7 +2,10 @@ {$template "/echarts"} -升级提醒:有 {{nodeUpgradeInfo.count}} 个边缘节点需要升级到 v{{nodeUpgradeInfo.version}} 版本 + + + 升级提醒:有 {{nodeUpgradeInfo.count}} 个边缘节点需要升级到 v{{nodeUpgradeInfo.version}} 版本 + 升级提醒:有 {{monitorNodeUpgradeInfo.count}} 个监控节点需要升级到 v{{monitorNodeUpgradeInfo.version}} 版本 升级提醒:有 {{userNodeUpgradeInfo.count}} 个用户节点需要升级到 v{{userNodeUpgradeInfo.version}} 版本 升级提醒:有 {{apiNodeUpgradeInfo.count}} 个API节点需要升级到 v{{apiNodeUpgradeInfo.version}} 版本 @@ -12,7 +15,7 @@ {$template "menu"} - + 集群 {{dashboard.countNodeClusters}}个 @@ -23,7 +26,7 @@ {{dashboard.countNodes}}个 - + API节点 {{dashboard.countAPINodes}}个 @@ -46,6 +49,7 @@ + 24小时流量趋势 15天流量趋势 @@ -55,4 +59,27 @@ - \ No newline at end of file + + + + + + 24小时访问量趋势 + 15天访问量趋势 + + + + + + + + + +域名访问排行 (24小时) + + + + + +节点访问排行 (24小时) + diff --git a/web/views/@default/dashboard/boards/index.js b/web/views/@default/dashboard/boards/index.js index 55458208..4616b9f0 100644 --- a/web/views/@default/dashboard/boards/index.js +++ b/web/views/@default/dashboard/boards/index.js @@ -3,6 +3,9 @@ Tea.context(function () { this.$delay(function () { this.reloadHourlyTrafficChart() + this.reloadHourlyRequestsChart() + this.reloadTopDomainsChart() + this.reloadTopNodesChart() let that = this window.addEventListener("resize", function () { @@ -28,86 +31,63 @@ Tea.context(function () { } } + this.reloadHourlyTrafficChart = function () { + let stats = this.hourlyTrafficStats + this.reloadTrafficChart("hourly-traffic-chart-box", stats, function (args) { + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].bytes > 0) { + cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100 + attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100 + } + + return stats[index].day + " " + stats[index].hour + "时总流量:" + teaweb.formatBytes(stats[index].bytes) + "缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "缓存命中率:" + cachedRatio + "%拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "拦截比例:" + attackRatio + "%" + }) + } + + this.reloadDailyTrafficChart = function () { + let stats = this.dailyTrafficStats + this.reloadTrafficChart("daily-traffic-chart-box", stats, function (args) { + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].bytes > 0) { + cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100 + attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100 + } + + return stats[index].day + "总流量:" + teaweb.formatBytes(stats[index].bytes) + "缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "缓存命中率:" + cachedRatio + "%拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "拦截比例:" + attackRatio + "%" + }) + } + this.resizeHourlyTrafficChart = function () { let chartBox = document.getElementById("hourly-traffic-chart-box") let chart = echarts.init(chartBox) chart.resize() } - this.reloadHourlyTrafficChart = function () { - let axis = teaweb.bytesAxis(this.hourlyTrafficStats, function (v) { - return v.bytes - }) - let chartBox = document.getElementById("hourly-traffic-chart-box") - let chart = echarts.init(chartBox) - let that = this - let option = { - xAxis: { - data: this.hourlyTrafficStats.map(function (v) { - return v.hour; - }) - }, - yAxis: { - axisLabel: { - formatter: function (v) { - return v + axis.unit - } - } - }, - tooltip: { - show: true, - trigger: "item", - formatter: function (args) { - let index = args.dataIndex - return that.hourlyTrafficStats[index].hour + "时:" + teaweb.formatBytes(that.hourlyTrafficStats[index].bytes) - } - }, - grid: { - left: 40, - top: 10, - right: 20 - }, - series: [ - { - name: "流量", - type: "line", - data: this.hourlyTrafficStats.map(function (v) { - return v.bytes / axis.divider; - }), - itemStyle: { - color: "#9DD3E8" - }, - lineStyle: { - color: "#9DD3E8" - }, - areaStyle: { - color: "#9DD3E8" - } - } - ], - animation: false - } - chart.setOption(option) - chart.resize() - } - this.resizeDailyTrafficChart = function () { let chartBox = document.getElementById("daily-traffic-chart-box") let chart = echarts.init(chartBox) chart.resize() } - this.reloadDailyTrafficChart = function () { - let axis = teaweb.bytesAxis(this.dailyTrafficStats, function (v) { + + this.reloadTrafficChart = function (chartId, stats, tooltipFunc) { + let axis = teaweb.bytesAxis(stats, function (v) { return v.bytes }) - let chartBox = document.getElementById("daily-traffic-chart-box") + let chartBox = document.getElementById(chartId) let chart = echarts.init(chartBox) let that = this let option = { xAxis: { - data: this.dailyTrafficStats.map(function (v) { - return v.day; + data: stats.map(function (v) { + if (v.hour != null) { + return v.hour + } + return v.day }) }, yAxis: { @@ -120,21 +100,19 @@ Tea.context(function () { tooltip: { show: true, trigger: "item", - formatter: function (args) { - let index = args.dataIndex - return that.dailyTrafficStats[index].day + ":" + teaweb.formatBytes(that.dailyTrafficStats[index].bytes) - } + formatter: tooltipFunc }, grid: { - left: 40, - top: 10, - right: 20 + left: 50, + top: 40, + right: 20, + bottom: 20 }, series: [ { - name: "流量", + name: "总流量", type: "line", - data: this.dailyTrafficStats.map(function (v) { + data: stats.map(function (v) { return v.bytes / axis.divider; }), itemStyle: { @@ -146,14 +124,234 @@ Tea.context(function () { areaStyle: { color: "#9DD3E8" } + }, + { + name: "缓存流量", + type: "line", + data: stats.map(function (v) { + return v.cachedBytes / axis.divider; + }), + itemStyle: { + color: "#61A0A8" + }, + lineStyle: { + color: "#61A0A8" + } + }, + { + name: "攻击流量", + type: "line", + data: stats.map(function (v) { + return v.attackBytes / axis.divider; + }), + itemStyle: { + color: "#F39494" + }, + lineStyle: { + color: "#F39494" + } } ], + legend: { + data: ["总流量", "缓存流量", "攻击流量"] + }, animation: false } chart.setOption(option) chart.resize() } + /** + * 请求数统计 + */ + this.requestsTab = "hourly" + + this.selectRequestsTab = function (tab) { + this.requestsTab = tab + if (tab == "hourly") { + this.$delay(function () { + this.reloadHourlyRequestsChart() + }) + } else if (tab == "daily") { + this.$delay(function () { + this.reloadDailyRequestsChart() + }) + } + } + + this.reloadHourlyRequestsChart = function () { + let stats = this.hourlyTrafficStats + this.reloadRequestsChart("hourly-requests-chart", "请求数统计", stats, function (args) { + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].countRequests > 0) { + cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100 + attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100 + } + + return stats[index].day + " " + stats[index].hour + "时总请求数:" + stats[index].countRequests + "缓存请求数:" + stats[index].countCachedRequests + "缓存命中率:" + cachedRatio + "%拦截攻击数:" + stats[index].countAttackRequests + "拦截比例:" + attackRatio + "%" + }) + } + + this.reloadDailyRequestsChart = function () { + let stats = this.dailyTrafficStats + this.reloadRequestsChart("daily-requests-chart", "请求数统计", stats, function (args) { + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].countRequests > 0) { + cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100 + attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100 + } + + return stats[index].day + "总请求数:" + stats[index].countRequests + "缓存请求数:" + stats[index].countCachedRequests + "缓存命中率:" + cachedRatio + "%拦截攻击数:" + stats[index].countAttackRequests + "拦截比例:" + attackRatio + "%" + }) + } + + this.reloadRequestsChart = function (chartId, name, stats, tooltipFunc) { + let chartBox = document.getElementById(chartId) + if (chartBox == null) { + return + } + + let axis = teaweb.countAxis(stats, function (v) { + return Math.max(v.countRequests, v.countCachedRequests) + }) + + let chart = echarts.init(chartBox) + let option = { + xAxis: { + data: stats.map(function (v) { + if (v.hour != null) { + return v.hour + } + if (v.day != null) { + return v.day + } + return "" + }) + }, + yAxis: { + axisLabel: { + formatter: function (value) { + return value + axis.unit + } + } + }, + tooltip: { + show: true, + trigger: "item", + formatter: tooltipFunc + }, + grid: { + left: 50, + top: 40, + right: 20, + bottom: 20 + }, + series: [ + { + name: "请求数", + type: "line", + data: stats.map(function (v) { + return v.countRequests / axis.divider + }), + itemStyle: { + color: "#9DD3E8" + }, + areaStyle: { + color: "#9DD3E8" + } + }, + { + name: "缓存请求数", + type: "line", + data: stats.map(function (v) { + return v.countCachedRequests / axis.divider + }), + itemStyle: { + color: "#61A0A8" + }, + areaStyle: { + color: "#61A0A8" + } + }, + { + name: "攻击请求数", + type: "line", + data: stats.map(function (v) { + return v.countAttackRequests / axis.divider; + }), + itemStyle: { + color: "#F39494" + }, + lineStyle: { + color: "#F39494" + } + } + ], + legend: { + data: ["请求数", "缓存请求数", "攻击请求数"] + }, + animation: true + } + chart.setOption(option) + chart.resize() + } + + // 节点排行 + this.reloadTopNodesChart = function () { + let that = this + let axis = teaweb.countAxis(this.topNodeStats, function (v) { + return v.countRequests + }) + teaweb.renderBarChart({ + id: "top-nodes-chart", + name: "节点", + values: this.topNodeStats, + x: function (v) { + return v.nodeName + }, + tooltip: function (args, stats) { + return stats[args.dataIndex].nodeName + "请求数:" + " " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + "流量:" + teaweb.formatBytes(stats[args.dataIndex].bytes) + }, + value: function (v) { + return v.countRequests / axis.divider; + }, + axis: axis, + click: function (args, stats) { + window.location = "/clusters/cluster/node?nodeId=" + stats[args.dataIndex].nodeId + "&clusterId=" + that.clusterId + } + }) + } + + // 域名排行 + this.reloadTopDomainsChart = function () { + let axis = teaweb.countAxis(this.topDomainStats, function (v) { + return v.countRequests + }) + teaweb.renderBarChart({ + id: "top-domains-chart", + name: "域名", + values: this.topDomainStats, + x: function (v) { + return v.domain + }, + tooltip: function (args, stats) { + return stats[args.dataIndex].domain + "请求数:" + " " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + "流量:" + teaweb.formatBytes(stats[args.dataIndex].bytes) + }, + value: function (v) { + return v.countRequests / axis.divider; + }, + axis: axis, + click: function (args, stats) { + let index = args.dataIndex + window.location = "/servers/server?serverId=" + stats[index].serverId + } + }) + } + /** * 升级提醒 */ diff --git a/web/views/@default/servers/server/boards/index.html b/web/views/@default/servers/server/boards/index.html index defb5443..d7000cbc 100644 --- a/web/views/@default/servers/server/boards/index.html +++ b/web/views/@default/servers/server/boards/index.html @@ -1,6 +1,12 @@ {$layout} {$template "/echarts"} + + 服务列表 + | + "{{server.name}}"看板 + + 24小时流量趋势 15天流量趋势 diff --git a/web/views/@default/servers/server/boards/index.js b/web/views/@default/servers/server/boards/index.js index dac4c9ca..7726ef6f 100644 --- a/web/views/@default/servers/server/boards/index.js +++ b/web/views/@default/servers/server/boards/index.js @@ -36,34 +36,30 @@ Tea.context(function () { this.reloadHourlyTrafficChart = function () { let stats = this.hourlyStats this.reloadTrafficChart("hourly-traffic-chart", "流量统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 流量: " + teaweb.formatBytes(stats[args.dataIndex].bytes) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].bytes > 0) { + cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100 + attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].bytes > 0) { - ratio = Math.round(stats[args.dataIndex].cachedBytes * 10000 / stats[args.dataIndex].bytes) / 100 - } - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 缓存流量: " + teaweb.formatBytes(stats[args.dataIndex].cachedBytes) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + " " + stats[index].hour + "时总流量:" + teaweb.formatBytes(stats[index].bytes) + "缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "缓存命中率:" + cachedRatio + "%拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "拦截比例:" + attackRatio + "%" }) } this.reloadDailyTrafficChart = function () { let stats = this.dailyStats this.reloadTrafficChart("daily-traffic-chart", "流量统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " 流量: " + teaweb.formatBytes(stats[args.dataIndex].bytes) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].bytes > 0) { + cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100 + attackRatio = Math.round(stats[index].attackBytes * 10000 / stats[index].bytes) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].bytes > 0) { - ratio = Math.round(stats[args.dataIndex].cachedBytes * 10000 / stats[args.dataIndex].bytes) / 100 - } - return stats[args.dataIndex].day + " 缓存流量: " + teaweb.formatBytes(stats[args.dataIndex].cachedBytes) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + "总流量:" + teaweb.formatBytes(stats[index].bytes) + "缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "缓存命中率:" + cachedRatio + "%拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "拦截比例:" + attackRatio + "%" }) } @@ -131,10 +127,23 @@ Tea.context(function () { areaStyle: { color: "#61A0A8" } + }, + { + name: "攻击流量", + type: "line", + data: stats.map(function (v) { + return v.attackBytes / axis.divider; + }), + itemStyle: { + color: "#F39494" + }, + lineStyle: { + color: "#F39494" + } } ], legend: { - data: ['流量', '缓存流量'] + data: ["流量", "缓存流量", "攻击流量"] }, animation: true } @@ -163,34 +172,30 @@ Tea.context(function () { this.reloadHourlyRequestsChart = function () { let stats = this.hourlyStats this.reloadRequestsChart("hourly-requests-chart", "请求数统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 请求数: " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].countRequests > 0) { + cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100 + attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].countRequests > 0) { - ratio = Math.round(stats[args.dataIndex].countCachedRequests * 10000 / stats[args.dataIndex].countRequests) / 100 - } - return stats[args.dataIndex].day + " " + stats[args.dataIndex].hour + "时 缓存请求数: " + teaweb.formatNumber(stats[args.dataIndex].countCachedRequests) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + " " + stats[index].hour + "时总请求数:" + stats[index].countRequests + "缓存请求数:" + stats[index].countCachedRequests + "缓存命中率:" + cachedRatio + "%拦截攻击数:" + stats[index].countAttackRequests + "拦截比例:" + attackRatio + "%" }) } this.reloadDailyRequestsChart = function () { let stats = this.dailyStats this.reloadRequestsChart("daily-requests-chart", "请求数统计", stats, function (args) { - if (args.seriesIndex == 0) { - return stats[args.dataIndex].day + " 请求数: " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + let index = args.dataIndex + let cachedRatio = 0 + let attackRatio = 0 + if (stats[index].countRequests > 0) { + cachedRatio = Math.round(stats[index].countCachedRequests * 10000 / stats[index].countRequests) / 100 + attackRatio = Math.round(stats[index].countAttackRequests * 10000 / stats[index].countRequests) / 100 } - if (args.seriesIndex == 1) { - let ratio = 0 - if (stats[args.dataIndex].countRequests > 0) { - ratio = Math.round(stats[args.dataIndex].countCachedRequests * 10000 / stats[args.dataIndex].countRequests) / 100 - } - return stats[args.dataIndex].day + " 缓存请求数: " + teaweb.formatNumber(stats[args.dataIndex].countCachedRequests) + ", 命中率:" + ratio + "%" - } - return "" + + return stats[index].day + "总请求数:" + stats[index].countRequests + "缓存请求数:" + stats[index].countCachedRequests + "缓存命中率:" + cachedRatio + "%拦截攻击数:" + stats[index].countAttackRequests + "拦截比例:" + attackRatio + "%" }) } @@ -261,10 +266,23 @@ Tea.context(function () { areaStyle: { color: "#61A0A8" } + }, + { + name: "攻击请求数", + type: "line", + data: stats.map(function (v) { + return v.countAttackRequests / axis.divider; + }), + itemStyle: { + color: "#F39494" + }, + lineStyle: { + color: "#F39494" + } } ], legend: { - data: ['请求数', '缓存请求数'] + data: ["请求数", "缓存请求数", "攻击请求数"] }, animation: true }