mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 13:10:26 +08:00 
			
		
		
		
	开源版本也显示域名排行、缓存流量趋势、攻击流量趋势
This commit is contained in:
		@@ -40,6 +40,10 @@ func (this *IndexAction) RunGet(params struct{}) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *IndexAction) RunPost(params struct{}) {
 | 
			
		||||
	// 读取看板数据
 | 
			
		||||
	resp, err := this.RPC().AdminRPC().ComposeAdminDashboard(this.AdminContext(), &pb.ComposeAdminDashboardRequest{
 | 
			
		||||
		ApiVersion: teaconst.APINodeVersion,
 | 
			
		||||
@@ -86,6 +90,12 @@ func (this *IndexAction) RunGet(params struct{}) {
 | 
			
		||||
		for _, stat := range resp.HourlyTrafficStats {
 | 
			
		||||
			statMaps = append(statMaps, maps.Map{
 | 
			
		||||
				"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:],
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
@@ -98,6 +108,11 @@ func (this *IndexAction) RunGet(params struct{}) {
 | 
			
		||||
		for _, stat := range resp.DailyTrafficStats {
 | 
			
		||||
			statMaps = append(statMaps, maps.Map{
 | 
			
		||||
				"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:] + "日",
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
@@ -172,6 +187,20 @@ 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,
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
		this.Data["topDomainStats"] = statMaps
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 指标
 | 
			
		||||
	{
 | 
			
		||||
		var chartMaps = []maps.Map{}
 | 
			
		||||
@@ -210,5 +239,5 @@ func (this *IndexAction) RunGet(params struct{}) {
 | 
			
		||||
		this.Data["metricCharts"] = chartMaps
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
	this.Success()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,24 +1,31 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "/echarts"}
 | 
			
		||||
 | 
			
		||||
<!-- 加载中 -->
 | 
			
		||||
<div style="margin-top: 0.8em">
 | 
			
		||||
    <div class="ui message loading" v-if="isLoading">
 | 
			
		||||
        <div class="ui active inline loader small"></div>    数据加载中...
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<!-- 没有节点提醒 -->
 | 
			
		||||
<div class="ui icon message warning" v-if="dashboard.defaultClusterId > 0 && dashboard.countNodes == 0">
 | 
			
		||||
<div class="ui icon message warning" v-if="!isLoading && dashboard.defaultClusterId > 0 && dashboard.countNodes == 0">
 | 
			
		||||
    <i class="icon warning circle"></i>
 | 
			
		||||
    <a :href="'/clusters/cluster/createNode?clusterId=' + dashboard.defaultClusterId">还没有在集群中添加节点,现在去添加?添加节点后才可部署网站服务。</a>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<!-- 升级提醒 -->
 | 
			
		||||
<div class="ui icon message error" v-if="nodeUpgradeInfo.count > 0">
 | 
			
		||||
<div class="ui icon message error" v-if="!isLoading && nodeUpgradeInfo.count > 0">
 | 
			
		||||
    <i class="icon warning circle"></i>
 | 
			
		||||
    <a href="/clusters">升级提醒:有 {{nodeUpgradeInfo.count}} 个边缘节点需要升级到 v{{nodeUpgradeInfo.version}} 版本</a><a href="" title="关闭" @click.prevent="closeMessage"><i class="ui icon remove small"></i></a>
 | 
			
		||||
</div>
 | 
			
		||||
<div class="ui icon message error" v-if="apiNodeUpgradeInfo.count > 0">
 | 
			
		||||
<div class="ui icon message error" v-if="!isLoading && apiNodeUpgradeInfo.count > 0">
 | 
			
		||||
    <i class="icon warning circle"></i>
 | 
			
		||||
    <a href="/api">升级提醒:有 {{apiNodeUpgradeInfo.count}} 个API节点需要升级到 v{{apiNodeUpgradeInfo.version}} 版本</a><a href="" title="关闭" @click.prevent="closeMessage"><i class="ui icon remove small"></i></a>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<!-- 统计图表 -->
 | 
			
		||||
<div class="ui three columns grid">
 | 
			
		||||
<div class="ui three columns grid" v-if="!isLoading">
 | 
			
		||||
    <div class="ui column">
 | 
			
		||||
        <h4>集群<link-icon href="/clusters" v-if="dashboard.canGoNodes"></link-icon></h4>
 | 
			
		||||
        <div class="value"><span>{{dashboard.countNodeClusters}}</span>个</div>
 | 
			
		||||
@@ -50,9 +57,9 @@
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div class="ui divider"></div>
 | 
			
		||||
<div class="ui divider" v-show="!isLoading"></div>
 | 
			
		||||
 | 
			
		||||
<div class="ui menu tabular">
 | 
			
		||||
<div class="ui menu tabular" v-show="!isLoading">
 | 
			
		||||
    <a href="" class="item" :class="{active: trafficTab == 'hourly'}" @click.prevent="selectTrafficTab('hourly')">24小时流量趋势</a>
 | 
			
		||||
    <a href="" class="item" :class="{active: trafficTab == 'daily'}" @click.prevent="selectTrafficTab('daily')">15天流量趋势</a>
 | 
			
		||||
</div>
 | 
			
		||||
@@ -63,6 +70,10 @@
 | 
			
		||||
<!-- 按日统计 -->
 | 
			
		||||
<div class="chart-box" id="daily-traffic-chart-box" v-show="trafficTab == 'daily'"></div>
 | 
			
		||||
 | 
			
		||||
<!-- 域名排行 -->
 | 
			
		||||
<h4 v-show="!isLoading">域名访问排行 <span>(24小时)</span></h4>
 | 
			
		||||
<div class="chart-box" id="top-domains-chart"></div>
 | 
			
		||||
 | 
			
		||||
<!-- 指标 -->
 | 
			
		||||
<div class="ui divider" v-if="metricCharts.length > 0"></div>
 | 
			
		||||
<metric-board>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,23 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.isLoading = true
 | 
			
		||||
	this.trafficTab = "hourly"
 | 
			
		||||
	this.metricCharts = []
 | 
			
		||||
	this.dashboard = {}
 | 
			
		||||
 | 
			
		||||
	this.$delay(function () {
 | 
			
		||||
		this.$post("$")
 | 
			
		||||
			.success(function (resp) {
 | 
			
		||||
				for (let k in resp.data) {
 | 
			
		||||
					this[k] = resp.data[k]
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				this.isLoading = false
 | 
			
		||||
 | 
			
		||||
				this.$delay(function () {
 | 
			
		||||
					this.reloadHourlyTrafficChart()
 | 
			
		||||
					this.reloadTopDomainsChart()
 | 
			
		||||
				})
 | 
			
		||||
			})
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	this.selectTrafficTab = function (tab) {
 | 
			
		||||
@@ -19,75 +34,48 @@ Tea.context(function () {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.reloadHourlyTrafficChart = function () {
 | 
			
		||||
		let axis = teaweb.bytesAxis(this.hourlyTrafficStats, function (v) {
 | 
			
		||||
			return v.bytes
 | 
			
		||||
		})
 | 
			
		||||
		let chartBox = document.getElementById("hourly-traffic-chart-box")
 | 
			
		||||
		let chart = teaweb.initChart(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 stats = this.hourlyTrafficStats
 | 
			
		||||
		this.reloadTrafficChart("hourly-traffic-chart-box", stats, function (args) {
 | 
			
		||||
			let index = args.dataIndex
 | 
			
		||||
					return that.hourlyTrafficStats[index].hour + "时:" + teaweb.formatBytes(that.hourlyTrafficStats[index].bytes)
 | 
			
		||||
			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
 | 
			
		||||
			}
 | 
			
		||||
			},
 | 
			
		||||
			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"
 | 
			
		||||
					},
 | 
			
		||||
					smooth: true
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			animation: false
 | 
			
		||||
		}
 | 
			
		||||
		chart.setOption(option)
 | 
			
		||||
		chart.resize()
 | 
			
		||||
 | 
			
		||||
			return stats[index].day + " " + stats[index].hour + "时<br/>总流量:" + teaweb.formatBytes(stats[index].bytes) + "<br/>缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "<br/>缓存命中率:" + cachedRatio + "%<br/>拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "<br/>拦截比例:" + attackRatio + "%"
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.reloadDailyTrafficChart = function () {
 | 
			
		||||
		let axis = teaweb.bytesAxis(this.dailyTrafficStats, function (v) {
 | 
			
		||||
		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 + "<br/>总流量:" + teaweb.formatBytes(stats[index].bytes) + "<br/>缓存流量:" + teaweb.formatBytes(stats[index].cachedBytes) + "<br/>缓存命中率:" + cachedRatio + "%<br/>拦截攻击流量:" + teaweb.formatBytes(stats[index].attackBytes) + "<br/>拦截比例:" + attackRatio + "%"
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 = teaweb.initChart(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: {
 | 
			
		||||
@@ -100,21 +88,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: {
 | 
			
		||||
@@ -127,14 +113,73 @@ Tea.context(function () {
 | 
			
		||||
						color: "#9DD3E8"
 | 
			
		||||
					},
 | 
			
		||||
					smooth: true
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					name: "缓存流量",
 | 
			
		||||
					type: "line",
 | 
			
		||||
					data: stats.map(function (v) {
 | 
			
		||||
						return v.cachedBytes / axis.divider;
 | 
			
		||||
					}),
 | 
			
		||||
					itemStyle: {
 | 
			
		||||
						color: "#61A0A8"
 | 
			
		||||
					},
 | 
			
		||||
					lineStyle: {
 | 
			
		||||
						color: "#61A0A8"
 | 
			
		||||
					},
 | 
			
		||||
					areaStyle: {},
 | 
			
		||||
					smooth: true
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					name: "攻击流量",
 | 
			
		||||
					type: "line",
 | 
			
		||||
					data: stats.map(function (v) {
 | 
			
		||||
						return v.attackBytes / axis.divider;
 | 
			
		||||
					}),
 | 
			
		||||
					itemStyle: {
 | 
			
		||||
						color: "#F39494"
 | 
			
		||||
					},
 | 
			
		||||
					areaStyle: {
 | 
			
		||||
						color: "#F39494"
 | 
			
		||||
					},
 | 
			
		||||
					smooth: true
 | 
			
		||||
				}
 | 
			
		||||
			],
 | 
			
		||||
			legend: {
 | 
			
		||||
				data: ["总流量", "缓存流量", "攻击流量"]
 | 
			
		||||
			},
 | 
			
		||||
			animation: false
 | 
			
		||||
		}
 | 
			
		||||
		chart.setOption(option)
 | 
			
		||||
		chart.resize()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// 域名排行
 | 
			
		||||
	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 + "<br/>请求数:" + " " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + "<br/>流量:" + 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
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * 升级提醒
 | 
			
		||||
	 */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user