展示监控信息

This commit is contained in:
奶爸 2019-12-09 23:45:23 +08:00
parent bfe6d48927
commit 8d791d91c1
9 changed files with 157 additions and 84 deletions

View File

@ -29,11 +29,13 @@ var (
Run: run, Run: run,
} }
clientID string clientID string
server string
clientSecret string clientSecret string
debug bool debug bool
) )
func main() { func main() {
rootCmd.PersistentFlags().StringVarP(&server, "server", "s", "localhost:5555", "客户端ID")
rootCmd.PersistentFlags().StringVarP(&clientID, "id", "i", "", "客户端ID") rootCmd.PersistentFlags().StringVarP(&clientID, "id", "i", "", "客户端ID")
rootCmd.PersistentFlags().StringVarP(&clientSecret, "secret", "p", "", "客户端Secret") rootCmd.PersistentFlags().StringVarP(&clientSecret, "secret", "p", "", "客户端Secret")
rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "开启Debug") rootCmd.PersistentFlags().BoolVarP(&debug, "debug", "d", false, "开启Debug")
@ -48,7 +50,6 @@ var reporting bool
var client pb.NezhaServiceClient var client pb.NezhaServiceClient
var ctx = context.Background() var ctx = context.Background()
var delayWhenError = time.Second * 10 var delayWhenError = time.Second * 10
var delayWhenReport = time.Second
func run(cmd *cobra.Command, args []string) { func run(cmd *cobra.Command, args []string) {
dao.Conf = &model.Config{ dao.Conf = &model.Config{
@ -67,7 +68,7 @@ func run(cmd *cobra.Command, args []string) {
log.Println("Try to reconnect ...") log.Println("Try to reconnect ...")
} }
for { for {
conn, err = grpc.Dial(":5555", grpc.WithInsecure(), grpc.WithPerRPCCredentials(&auth)) conn, err = grpc.Dial(server, grpc.WithInsecure(), grpc.WithPerRPCCredentials(&auth))
if err != nil { if err != nil {
log.Printf("grpc.Dial err: %v", err) log.Printf("grpc.Dial err: %v", err)
retry() retry()
@ -121,12 +122,12 @@ func reportState() {
defer log.Printf("reportState exit %v %v => %v", endReport, time.Now(), err) defer log.Printf("reportState exit %v %v => %v", endReport, time.Now(), err)
for { for {
if endReport.After(time.Now()) { if endReport.After(time.Now()) {
_, err = client.ReportState(ctx, monitor.GetState(0).PB()) monitor.TrackNetworkSpeed()
_, err = client.ReportState(ctx, monitor.GetState(1).PB())
if err != nil { if err != nil {
log.Printf("reportState error %v", err) log.Printf("reportState error %v", err)
time.Sleep(delayWhenError) time.Sleep(delayWhenError)
} }
} }
time.Sleep(delayWhenReport)
} }
} }

View File

@ -24,12 +24,18 @@ func ServeWeb() {
"tf": func(t time.Time) string { "tf": func(t time.Time) string {
return t.Format("2006年1月2号") return t.Format("2006年1月2号")
}, },
"stf": func(s uint64) string {
return time.Unix(int64(s), 0).Format("2006年1月2号 15:04")
},
"fs": func() string { "fs": func() string {
if !dao.Conf.Debug { if !dao.Conf.Debug {
return "" return ""
} }
return fmt.Sprintf("%d", time.Now().UnixNano()) return fmt.Sprintf("%d", time.Now().UnixNano())
}, },
"sf": func(duration uint64) string {
return time.Duration(time.Duration(duration) * time.Second).String()
},
"bf": func(b uint64) string { "bf": func(b uint64) string {
return bytefmt.ByteSize(b) return bytefmt.ByteSize(b)
}, },

View File

@ -10,44 +10,53 @@ const (
// State .. // State ..
type State struct { type State struct {
CPU float64 CPU float64
MemTotal uint64 MemTotal uint64
MemUsed uint64 MemUsed uint64
SwapTotal uint64 SwapTotal uint64
SwapUsed uint64 SwapUsed uint64
DiskTotal uint64 DiskTotal uint64
DiskUsed uint64 DiskUsed uint64
NetIn uint64 NetInTransfer uint64
NetOut uint64 NetOutTransfer uint64
NetInSpeed uint64
NetOutSpeed uint64
Uptime uint64
} }
// PB .. // PB ..
func (s *State) PB() *pb.State { func (s *State) PB() *pb.State {
return &pb.State{ return &pb.State{
Cpu: s.CPU, Cpu: s.CPU,
MemTotal: s.MemTotal, MemTotal: s.MemTotal,
MemUsed: s.MemUsed, MemUsed: s.MemUsed,
SwapTotal: s.SwapTotal, SwapTotal: s.SwapTotal,
SwapUsed: s.SwapUsed, SwapUsed: s.SwapUsed,
DiskTotal: s.DiskTotal, DiskTotal: s.DiskTotal,
DiskUsed: s.DiskUsed, DiskUsed: s.DiskUsed,
NetIn: s.NetIn, NetInTransfer: s.NetInTransfer,
NetOut: s.NetOut, NetOutTransfer: s.NetOutTransfer,
NetInSpeed: s.NetInSpeed,
NetOutSpeed: s.NetOutSpeed,
Uptime: s.Uptime,
} }
} }
// PB2State .. // PB2State ..
func PB2State(s *pb.State) State { func PB2State(s *pb.State) State {
return State{ return State{
CPU: s.GetCpu(), CPU: s.GetCpu(),
MemTotal: s.GetMemTotal(), MemTotal: s.GetMemTotal(),
MemUsed: s.GetMemUsed(), MemUsed: s.GetMemUsed(),
SwapTotal: s.GetSwapTotal(), SwapTotal: s.GetSwapTotal(),
SwapUsed: s.GetSwapUsed(), SwapUsed: s.GetSwapUsed(),
DiskTotal: s.GetDiskTotal(), DiskTotal: s.GetDiskTotal(),
DiskUsed: s.GetDiskUsed(), DiskUsed: s.GetDiskUsed(),
NetIn: s.GetNetIn(), NetInTransfer: s.GetNetInTransfer(),
NetOut: s.GetNetOut(), NetOutTransfer: s.GetNetOutTransfer(),
NetInSpeed: s.GetNetInSpeed(),
NetOutSpeed: s.GetNetOutSpeed(),
Uptime: s.GetUptime(),
} }
} }
@ -58,8 +67,7 @@ type Host struct {
CPU []string CPU []string
Arch string Arch string
Virtualization string Virtualization string
Uptime string BootTime uint64
BootTime string
IP string IP string
CountryCode string CountryCode string
Version string Version string
@ -73,7 +81,6 @@ func (h *Host) PB() *pb.Host {
Cpu: h.CPU, Cpu: h.CPU,
Arch: h.Arch, Arch: h.Arch,
Virtualization: h.Virtualization, Virtualization: h.Virtualization,
Uptime: h.Uptime,
BootTime: h.BootTime, BootTime: h.BootTime,
Ip: h.IP, Ip: h.IP,
CountryCode: h.CountryCode, CountryCode: h.CountryCode,
@ -89,7 +96,6 @@ func PB2Host(h *pb.Host) Host {
CPU: h.GetCpu(), CPU: h.GetCpu(),
Arch: h.GetArch(), Arch: h.GetArch(),
Virtualization: h.GetVirtualization(), Virtualization: h.GetVirtualization(),
Uptime: h.GetUptime(),
BootTime: h.GetBootTime(), BootTime: h.GetBootTime(),
IP: h.GetIp(), IP: h.GetIp(),
CountryCode: h.GetCountryCode(), CountryCode: h.GetCountryCode(),

View File

@ -13,6 +13,7 @@ import (
// CommonEnvironment .. // CommonEnvironment ..
func CommonEnvironment(c *gin.Context, data map[string]interface{}) gin.H { func CommonEnvironment(c *gin.Context, data map[string]interface{}) gin.H {
data["MatchedPath"] = c.MustGet("MatchedPath") data["MatchedPath"] = c.MustGet("MatchedPath")
data["Version"] = dao.Version
// 站点标题 // 站点标题
if t, has := data["Title"]; !has { if t, has := data["Title"]; !has {
data["Title"] = dao.Conf.Site.Brand data["Title"] = dao.Conf.Site.Brand

View File

@ -14,11 +14,10 @@ message Host {
repeated string cpu = 3; repeated string cpu = 3;
string arch = 4; string arch = 4;
string virtualization = 5; string virtualization = 5;
string uptime = 6; uint64 boot_time = 6;
string boot_time = 7; string ip = 7;
string ip = 8; string country_code = 8;
string country_code = 9; string version = 9;
string version = 10;
} }
message State { message State {
@ -29,8 +28,11 @@ message State {
uint64 swap_used = 5; uint64 swap_used = 5;
uint64 disk_total = 6; uint64 disk_total = 6;
uint64 disk_used = 7; uint64 disk_used = 7;
uint64 net_in = 8; uint64 net_in_transfer = 8;
uint64 net_out = 9; uint64 net_out_transfer = 9;
uint64 net_in_speed = 10;
uint64 net_out_speed = 11;
uint64 uptime = 12;
} }
message Receipt{ message Receipt{

View File

@ -1,7 +1,7 @@
{{define "common/footer"}} {{define "common/footer"}}
<div class="ui inverted vertical footer segment"> <div class="ui inverted vertical footer segment">
<div class="ui center aligned text container"> <div class="ui center aligned text container">
本系统由 <a href="https://github.com/p14yground/nezha" target="_blank">哪吒面板</a> 强力驱动 本系统由 <a href="https://github.com/p14yground/nezha" target="_blank">哪吒面板</a>(v{{.Version}}) 强力驱动
</div> </div>
</div> </div>
<script src="https://cdnjs.loli.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="https://cdnjs.loli.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

View File

@ -11,8 +11,14 @@
class="{{$server.Host.CountryCode}} flag"></i>{{end}}{{$server.Name}} class="{{$server.Host.CountryCode}} flag"></i>{{end}}{{$server.Name}}
<i data-html=" <i data-html="
<div class='content'> <div class='content'>
{{$server.Host}} 系统:{{$server.Host.Platform}}-{{$server.Host.PlatformVersion}} [{{if $server.Host.Virtualization}}{{$server.Host.Virtualization}}:{{end}}{{$server.Host.Arch}}]<br>
{{$server.State}} CPU{{$server.Host.CPU}}<br>
硬盘:{{$server.State.DiskUsed|bf}}/{{$server.State.DiskTotal|bf}}<br>
内存:{{$server.State.MemUsed|bf}}/{{$server.State.MemTotal|bf}}<br>
交换:{{$server.State.SwapUsed|bf}}/{{$server.State.SwapTotal|bf}}<br>
流量:<i class='arrow alternate circle down outline icon'></i>{{$server.State.NetInTransfer|bf}} <i class='arrow alternate circle up outline icon'></i>{{$server.State.NetOutTransfer|bf}}<br>
启动:{{$server.Host.BootTime|stf}}<br>
版本v{{$server.Host.Version}}<br>
</div>" class="yellow info circle icon"></i> </div>" class="yellow info circle icon"></i>
</div> </div>
<div class="description"> <div class="description">
@ -25,15 +31,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="three wide column">硬盘</div>
<div class="thirteen wide column">
<div class="ui active progress" data-value="{{$server.State.DiskUsed}}"
data-total="{{$server.State.DiskTotal}}">
<div class="bar">
<div class="progress"></div>
</div>
</div>
</div>
<div class="three wide column">内存</div> <div class="three wide column">内存</div>
<div class="thirteen wide column"> <div class="thirteen wide column">
<div class="ui active progress" data-value="{{$server.State.MemUsed}}" <div class="ui active progress" data-value="{{$server.State.MemUsed}}"
@ -43,10 +40,33 @@
</div> </div>
</div> </div>
</div> </div>
<div class="three wide column">交换</div>
<div class="thirteen wide column">
<div class="ui active progress" data-value="{{$server.State.SwapUsed}}"
data-total="{{$server.State.SwapTotal}}">
<div class="bar">
<div class="progress"></div>
</div>
</div>
</div>
<div class="three wide column">网络</div> <div class="three wide column">网络</div>
<div class="thirteen wide column"> <div class="thirteen wide column">
<i class="arrow alternate circle down outline icon"></i>{{$server.State.NetIn|bf}} <i
<i class="arrow alternate circle up outline icon"></i>{{$server.State.NetOut|bf}} class="arrow alternate circle down outline icon"></i>{{$server.State.NetInSpeed|bf}}/s
<i class="arrow alternate circle up outline icon"></i>{{$server.State.NetOutSpeed|bf}}/s
</div>
<div class="three wide column">硬盘</div>
<div class="thirteen wide column">
<div class="ui active progress" data-value="{{$server.State.DiskUsed}}"
data-total="{{$server.State.DiskTotal}}">
<div class="bar">
<div class="progress"></div>
</div>
</div>
</div>
<div class="three wide column">在线</div>
<div class="thirteen wide column">
<i class="clock icon"></i>{{$server.State.Uptime|sf}}
</div> </div>
</div> </div>
</div> </div>

View File

@ -26,3 +26,6 @@ var ServerList map[string]*model.Server
// ServerLock .. // ServerLock ..
var ServerLock sync.RWMutex var ServerLock sync.RWMutex
// Version ..
var Version = "debug"

View File

@ -15,6 +15,7 @@ import (
"github.com/shirou/gopsutil/net" "github.com/shirou/gopsutil/net"
"github.com/p14yground/nezha/model" "github.com/p14yground/nezha/model"
"github.com/p14yground/nezha/service/dao"
) )
type ipDotSbGeoIP struct { type ipDotSbGeoIP struct {
@ -22,6 +23,8 @@ type ipDotSbGeoIP struct {
IP string IP string
} }
var netInSpeed, netOutSpeed, netInTransfer, netOutTransfer, lastUpdate uint64
// GetHost .. // GetHost ..
func GetHost() *model.Host { func GetHost() *model.Host {
hi, _ := host.Info() hi, _ := host.Info()
@ -46,49 +49,80 @@ func GetHost() *model.Host {
CPU: cpus, CPU: cpus,
Arch: hi.KernelArch, Arch: hi.KernelArch,
Virtualization: hi.VirtualizationSystem, Virtualization: hi.VirtualizationSystem,
Uptime: fmt.Sprintf("%v", hi.Uptime), BootTime: hi.BootTime,
BootTime: fmt.Sprintf("%v", hi.BootTime),
IP: ip.IP, IP: ip.IP,
CountryCode: strings.ToLower(ip.CountryCode), CountryCode: strings.ToLower(ip.CountryCode),
Version: dao.Version,
} }
} }
// GetState .. // GetState ..
func GetState(delay uint64) *model.State { func GetState(delay int64) *model.State {
hi, _ := host.Info()
// Memory // Memory
mv, _ := mem.VirtualMemory() mv, _ := mem.VirtualMemory()
ms, _ := mem.SwapMemory() ms, _ := mem.SwapMemory()
// Disk
var diskTotal, diskUsed uint64
dparts, _ := disk.Partitions(true)
for _, part := range dparts {
u, _ := disk.Usage(part.Mountpoint)
diskTotal += u.Total
diskUsed += u.Used
}
// CPU // CPU
var cpuPercent float64 var cpuPercent float64
cp, err := cpu.Percent(time.Second*time.Duration(delay), false) cp, err := cpu.Percent(time.Second*time.Duration(delay), false)
if err == nil { if err == nil {
cpuPercent = cp[0] cpuPercent = cp[0]
}
// Disk
var diskTotal, diskUsed uint64
dparts, _ := disk.Partitions(true)
var lastDevice string
for _, part := range dparts {
u, _ := disk.Usage(part.Mountpoint)
if lastDevice != part.Device {
diskTotal += u.Total
lastDevice = part.Device
}
diskUsed += u.Used
}
}
// Network
var netIn, netOut uint64
nc, err := net.IOCounters(false)
if err == nil {
netIn = nc[0].BytesRecv
netOut = nc[0].BytesSent
}
return &model.State{ return &model.State{
CPU: cpuPercent, CPU: cpuPercent,
MemTotal: mv.Total, MemTotal: mv.Total,
MemUsed: mv.Used, MemUsed: mv.Used,
SwapTotal: ms.Total, SwapTotal: ms.Total,
SwapUsed: ms.Used, SwapUsed: ms.Used,
DiskTotal: diskTotal, DiskTotal: diskTotal,
DiskUsed: diskUsed, DiskUsed: diskUsed,
NetIn: netIn, NetInTransfer: netInTransfer,
NetOut: netOut, NetOutTransfer: netOutTransfer,
NetInSpeed: netInSpeed,
NetOutSpeed: netOutSpeed,
Uptime: hi.Uptime,
}
}
// TrackNetworkSpeed ..
func TrackNetworkSpeed() {
var innerNetInTransfer, innerNetOutTransfer uint64
nc, err := net.IOCounters(true)
if err == nil {
for i := 0; i < len(nc); i++ {
if strings.HasPrefix(nc[i].Name, "e") {
innerNetInTransfer += nc[i].BytesRecv
innerNetOutTransfer += nc[i].BytesSent
}
}
if netInTransfer == 0 {
netInTransfer = innerNetInTransfer
}
if netOutTransfer == 0 {
netOutTransfer = innerNetOutTransfer
}
diff := uint64(time.Now().Unix())
if lastUpdate == 0 {
lastUpdate = diff
return
}
diff -= lastUpdate
if diff > 0 {
netInSpeed = (innerNetInTransfer - netInTransfer) / diff
netOutSpeed = (innerNetOutTransfer - netOutTransfer) / diff
}
} }
} }