mirror of https://github.com/bjdgyc/anylink.git
首页图表可查看用户组下的在线数、网络吞吐量
This commit is contained in:
parent
5586b27319
commit
48bebadc6b
|
@ -47,6 +47,16 @@ func GroupNames(w http.ResponseWriter, r *http.Request) {
|
||||||
RespSucess(w, data)
|
RespSucess(w, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GroupNamesIds(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var names = dbdata.GetGroupNamesIds()
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"count": len(names),
|
||||||
|
"page_size": 0,
|
||||||
|
"datas": names,
|
||||||
|
}
|
||||||
|
RespSucess(w, data)
|
||||||
|
}
|
||||||
|
|
||||||
func GroupDetail(w http.ResponseWriter, r *http.Request) {
|
func GroupDetail(w http.ResponseWriter, r *http.Request) {
|
||||||
_ = r.ParseForm()
|
_ = r.ParseForm()
|
||||||
idS := r.FormValue("id")
|
idS := r.FormValue("id")
|
||||||
|
|
|
@ -62,6 +62,7 @@ func StartAdmin() {
|
||||||
|
|
||||||
r.HandleFunc("/group/list", GroupList)
|
r.HandleFunc("/group/list", GroupList)
|
||||||
r.HandleFunc("/group/names", GroupNames)
|
r.HandleFunc("/group/names", GroupNames)
|
||||||
|
r.HandleFunc("/group/names_ids", GroupNamesIds)
|
||||||
r.HandleFunc("/group/detail", GroupDetail)
|
r.HandleFunc("/group/detail", GroupDetail)
|
||||||
r.HandleFunc("/group/set", GroupSet)
|
r.HandleFunc("/group/set", GroupSet)
|
||||||
r.HandleFunc("/group/del", GroupDel)
|
r.HandleFunc("/group/del", GroupDel)
|
||||||
|
|
|
@ -32,6 +32,11 @@ type ValData struct {
|
||||||
Note string `json:"note"`
|
Note string `json:"note"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GroupNameId struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
// type Group struct {
|
// type Group struct {
|
||||||
// Id int `json:"id" xorm:"pk autoincr not null"`
|
// Id int `json:"id" xorm:"pk autoincr not null"`
|
||||||
// Name string `json:"name" xorm:"varchar(60) not null unique"`
|
// Name string `json:"name" xorm:"varchar(60) not null unique"`
|
||||||
|
@ -64,6 +69,20 @@ func GetGroupNames() []string {
|
||||||
return names
|
return names
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetGroupNamesIds() []GroupNameId {
|
||||||
|
var datas []Group
|
||||||
|
err := Find(&datas, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
base.Error(err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var names []GroupNameId
|
||||||
|
for _, v := range datas {
|
||||||
|
names = append(names, GroupNameId{Id: v.Id, Name: v.Name})
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
func SetGroup(g *Group) error {
|
func SetGroup(g *Group) error {
|
||||||
var err error
|
var err error
|
||||||
if g.Name == "" {
|
if g.Name == "" {
|
||||||
|
|
|
@ -63,4 +63,10 @@ func TestGetGroupNames(t *testing.T) {
|
||||||
for _, v := range gs {
|
for _, v := range gs {
|
||||||
ast.Equal(true, utils.InArrStr(gAll, v))
|
ast.Equal(true, utils.InArrStr(gAll, v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gni := GetGroupNamesIds()
|
||||||
|
for _, v := range gni {
|
||||||
|
ast.NotEqual(0, v.Id)
|
||||||
|
ast.Equal(true, utils.InArrStr(gAll, v.Name))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package dbdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStatsInfo(t *testing.T) {
|
||||||
|
ast := assert.New(t)
|
||||||
|
|
||||||
|
preIpData()
|
||||||
|
defer closeIpdata()
|
||||||
|
|
||||||
|
ast.True(StatsInfoIns.ValidAction("online"))
|
||||||
|
ast.False(StatsInfoIns.ValidAction("diskio"))
|
||||||
|
ast.True(StatsInfoIns.ValidScope("30d"))
|
||||||
|
ast.False(StatsInfoIns.ValidScope("60d"))
|
||||||
|
|
||||||
|
up := uint32(100)
|
||||||
|
down := uint32(300)
|
||||||
|
upGroups := map[int]uint32{1: up}
|
||||||
|
downGroups := map[int]uint32{1: down}
|
||||||
|
numGroups := map[int]int{1: 5}
|
||||||
|
// online
|
||||||
|
numData, _ := json.Marshal(numGroups)
|
||||||
|
so := &StatsOnline{Num: 1, NumGroups: string(numData)}
|
||||||
|
// network
|
||||||
|
upData, _ := json.Marshal(upGroups)
|
||||||
|
downData, _ := json.Marshal(downGroups)
|
||||||
|
sn := &StatsNetwork{Up: up, Down: down, UpGroups: string(upData), DownGroups: string(downData)}
|
||||||
|
// cpu
|
||||||
|
sc := &StatsCpu{Percent: 0.3}
|
||||||
|
// mem
|
||||||
|
sm := &StatsMem{Percent: 24.50}
|
||||||
|
|
||||||
|
StatsInfoIns.SetRealTime("online", so)
|
||||||
|
StatsInfoIns.GetRealTime("online")
|
||||||
|
StatsInfoIns.SaveStatsInfo(so, sn, sc, sm)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
_, err = StatsInfoIns.GetData("online", "1h")
|
||||||
|
ast.Nil(err)
|
||||||
|
|
||||||
|
_, err = StatsInfoIns.GetData("network", "1h")
|
||||||
|
ast.Nil(err)
|
||||||
|
|
||||||
|
_, err = StatsInfoIns.GetData("cpu", "1h")
|
||||||
|
ast.Nil(err)
|
||||||
|
|
||||||
|
_, err = StatsInfoIns.GetData("mem", "1h")
|
||||||
|
ast.Nil(err)
|
||||||
|
|
||||||
|
}
|
|
@ -22,9 +22,9 @@ func saveStatsInfo() {
|
||||||
for range tick.C {
|
for range tick.C {
|
||||||
up := uint32(0)
|
up := uint32(0)
|
||||||
down := uint32(0)
|
down := uint32(0)
|
||||||
upGroups := make(map[string]uint32)
|
upGroups := make(map[int]uint32)
|
||||||
downGroups := make(map[string]uint32)
|
downGroups := make(map[int]uint32)
|
||||||
numGroups := make(map[string]int)
|
numGroups := make(map[int]int)
|
||||||
onlineNum := 0
|
onlineNum := 0
|
||||||
sessMux.Lock()
|
sessMux.Lock()
|
||||||
for _, v := range sessions {
|
for _, v := range sessions {
|
||||||
|
@ -32,12 +32,16 @@ func saveStatsInfo() {
|
||||||
if v.IsActive {
|
if v.IsActive {
|
||||||
// 在线人数
|
// 在线人数
|
||||||
onlineNum += 1
|
onlineNum += 1
|
||||||
numGroups[v.Group] += 1
|
numGroups[v.CSess.Group.Id] += 1
|
||||||
// 网络吞吐
|
// 网络吞吐
|
||||||
userUp := atomic.LoadUint32(&v.CSess.BandwidthUpPeriod)
|
userUp := atomic.LoadUint32(&v.CSess.BandwidthUpPeriod)
|
||||||
userDown := atomic.LoadUint32(&v.CSess.BandwidthDownPeriod)
|
userDown := atomic.LoadUint32(&v.CSess.BandwidthDownPeriod)
|
||||||
upGroups[v.Group] += userUp
|
if userUp > 0 {
|
||||||
downGroups[v.Group] += userDown
|
upGroups[v.CSess.Group.Id] += userUp
|
||||||
|
}
|
||||||
|
if userDown > 0 {
|
||||||
|
downGroups[v.CSess.Group.Id] += userDown
|
||||||
|
}
|
||||||
up += userUp
|
up += userUp
|
||||||
down += userDown
|
down += userDown
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,12 @@
|
||||||
<el-row class="line-chart-box" gutter="20">
|
<el-row class="line-chart-box" gutter="20">
|
||||||
<el-col :span="12" class="line-chart-col">
|
<el-col :span="12" class="line-chart-col">
|
||||||
<LineChart :chart-data="lineChart.online"/>
|
<LineChart :chart-data="lineChart.online"/>
|
||||||
|
<div class="chart-group-name">
|
||||||
|
<el-select size="mini" v-model="lineChartGroup.online" @change="lineChartGroupChange('online')">
|
||||||
|
<el-option v-for="(item,index) in groupNames" :key="index" :label="item.text" :value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
<div class="time-range">
|
<div class="time-range">
|
||||||
<el-radio-group v-model="lineChartScope.online" size="mini" @change="((label)=>{lineChartScopeChange('online', label)})">
|
<el-radio-group v-model="lineChartScope.online" size="mini" @change="((label)=>{lineChartScopeChange('online', label)})">
|
||||||
<el-radio-button label="rt" >实时</el-radio-button>
|
<el-radio-button label="rt" >实时</el-radio-button>
|
||||||
|
@ -58,6 +64,12 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12" class="line-chart-col">
|
<el-col :span="12" class="line-chart-col">
|
||||||
<LineChart :chart-data="lineChart.network"/>
|
<LineChart :chart-data="lineChart.network"/>
|
||||||
|
<div class="chart-group-name">
|
||||||
|
<el-select size="mini" v-model="lineChartGroup.network" @change="lineChartGroupChange('network')">
|
||||||
|
<el-option v-for="(item,index) in groupNames" :key="index" :label="item.text" :value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
<div class="time-range">
|
<div class="time-range">
|
||||||
<el-radio-group v-model="lineChartScope.network" size="mini" @change="((label)=>{lineChartScopeChange('network', label)})">
|
<el-radio-group v-model="lineChartScope.network" size="mini" @change="((label)=>{lineChartScopeChange('network', label)})">
|
||||||
<el-radio-button label="rt" >实时</el-radio-button>
|
<el-radio-button label="rt" >实时</el-radio-button>
|
||||||
|
@ -119,6 +131,7 @@ export default {
|
||||||
group: 0,
|
group: 0,
|
||||||
ip_map: 0,
|
ip_map: 0,
|
||||||
},
|
},
|
||||||
|
groupNames:[],
|
||||||
lineChart: {
|
lineChart: {
|
||||||
online: {
|
online: {
|
||||||
title: '用户在线数',
|
title: '用户在线数',
|
||||||
|
@ -161,6 +174,10 @@ export default {
|
||||||
cpu : "rt",
|
cpu : "rt",
|
||||||
mem : "rt"
|
mem : "rt"
|
||||||
},
|
},
|
||||||
|
lineChartGroup : {
|
||||||
|
online: "",
|
||||||
|
network: "",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -169,6 +186,7 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getData()
|
this.getData()
|
||||||
|
this.getGroups()
|
||||||
this.getAllStats()
|
this.getAllStats()
|
||||||
const chartsTimer = setInterval(() => {
|
const chartsTimer = setInterval(() => {
|
||||||
this.getAllStats()
|
this.getAllStats()
|
||||||
|
@ -219,15 +237,22 @@ export default {
|
||||||
formatOnline(data) {
|
formatOnline(data) {
|
||||||
let timeFormat = this.getTimeFormat(data.scope)
|
let timeFormat = this.getTimeFormat(data.scope)
|
||||||
let chartData = this.lineChart[data.action]
|
let chartData = this.lineChart[data.action]
|
||||||
|
let chooseGroup = this.lineChartGroup[data.action]
|
||||||
let datas = data.datas
|
let datas = data.datas
|
||||||
|
let xnum = 0
|
||||||
chartData.xname = []
|
chartData.xname = []
|
||||||
chartData.xdata["在线人数"] = []
|
chartData.xdata["在线人数"] = []
|
||||||
for(var i=0; i<datas.length;i++){
|
for(var i=0; i<datas.length;i++){
|
||||||
chartData.xname[i] = this.dateFormat(datas[i].created_at, timeFormat)
|
chartData.xname[i] = this.dateFormat(datas[i].created_at, timeFormat)
|
||||||
chartData.xdata["在线人数"][i] = datas[i].num
|
xnum = datas[i].num
|
||||||
|
if (chooseGroup != "" && xnum > 0) {
|
||||||
|
let num_groups = JSON.parse(datas[i].num_groups)
|
||||||
|
xnum = ! num_groups[chooseGroup] ? 0 : num_groups[chooseGroup]
|
||||||
|
}
|
||||||
|
chartData.xdata["在线人数"][i] = xnum
|
||||||
}
|
}
|
||||||
// 实时更新在线数
|
// 实时更新在线数
|
||||||
if (data.scope == "rt") {
|
if (data.scope == "rt" && chooseGroup == "") {
|
||||||
this.counts.online = datas[datas.length - 1].num
|
this.counts.online = datas[datas.length - 1].num
|
||||||
}
|
}
|
||||||
this.lineChart[data.action] = chartData
|
this.lineChart[data.action] = chartData
|
||||||
|
@ -235,14 +260,28 @@ export default {
|
||||||
formatNetwork(data) {
|
formatNetwork(data) {
|
||||||
let timeFormat = this.getTimeFormat(data.scope)
|
let timeFormat = this.getTimeFormat(data.scope)
|
||||||
let chartData = this.lineChart[data.action]
|
let chartData = this.lineChart[data.action]
|
||||||
|
let chooseGroup = this.lineChartGroup[data.action]
|
||||||
let datas = data.datas
|
let datas = data.datas
|
||||||
|
let xnumUp = 0, xnumDown = 0
|
||||||
chartData.xname = []
|
chartData.xname = []
|
||||||
chartData.xdata["上行流量"] = []
|
chartData.xdata["上行流量"] = []
|
||||||
chartData.xdata["下行流量"] = []
|
chartData.xdata["下行流量"] = []
|
||||||
for(var i=0; i<datas.length;i++){
|
for(var i=0; i<datas.length;i++){
|
||||||
chartData.xname[i] = this.dateFormat(datas[i].created_at, timeFormat)
|
chartData.xname[i] = this.dateFormat(datas[i].created_at, timeFormat)
|
||||||
chartData.xdata["上行流量"][i] = this.toMbps(datas[i].up)
|
xnumUp = datas[i].up
|
||||||
chartData.xdata["下行流量"][i] = this.toMbps(datas[i].down)
|
xnumDown = datas[i].down
|
||||||
|
if (chooseGroup != "") {
|
||||||
|
if (xnumUp > 0) {
|
||||||
|
let upGroups = JSON.parse(datas[i].up_groups)
|
||||||
|
xnumUp = ! upGroups[chooseGroup] ? 0 : upGroups[chooseGroup]
|
||||||
|
}
|
||||||
|
if (xnumDown > 0) {
|
||||||
|
let downGroups = JSON.parse(datas[i].down_groups)
|
||||||
|
xnumDown = ! downGroups[chooseGroup] ? 0 : downGroups[chooseGroup]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chartData.xdata["上行流量"][i] = this.toMbps(xnumUp)
|
||||||
|
chartData.xdata["下行流量"][i] = this.toMbps(xnumDown)
|
||||||
}
|
}
|
||||||
this.lineChart[data.action] = chartData
|
this.lineChart[data.action] = chartData
|
||||||
},
|
},
|
||||||
|
@ -301,6 +340,23 @@ export default {
|
||||||
jump(path) {
|
jump(path) {
|
||||||
this.$router.push(path);
|
this.$router.push(path);
|
||||||
},
|
},
|
||||||
|
getGroups() {
|
||||||
|
axios.get('/group/names_ids', {}).then(resp => {
|
||||||
|
var data = resp.data.data
|
||||||
|
var groupNames = []
|
||||||
|
groupNames[0] = {text:"全部", value:""}
|
||||||
|
for(var i=0; i<data.datas.length;i++){
|
||||||
|
groupNames[i+1] = {text:data.datas[i].name, value:data.datas[i].id}
|
||||||
|
}
|
||||||
|
this.groupNames = groupNames
|
||||||
|
}).catch(error => {
|
||||||
|
this.$message.error('哦,请求出错');
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
lineChartGroupChange(action) {
|
||||||
|
this.getStatsData(action, this.lineChartScope[action]);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -309,6 +365,7 @@ export default {
|
||||||
.panel-group {
|
.panel-group {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-panel {
|
.card-panel {
|
||||||
display: flex;
|
display: flex;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
@ -368,4 +425,17 @@ export default {
|
||||||
right: 5px;
|
right: 5px;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.chart-group-name {
|
||||||
|
position: absolute;
|
||||||
|
left: 110px;
|
||||||
|
top: 5px;
|
||||||
|
width: 130px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .el-radio-button--mini .el-radio-button__inner {
|
||||||
|
padding: 7px 8px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue