first commit
This commit is contained in:
commit
fc0567db35
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
nezha-recoder.exe
|
||||
nezha-recoder
|
6
configs/config.go
Normal file
6
configs/config.go
Normal file
@ -0,0 +1,6 @@
|
||||
package configs
|
||||
|
||||
const (
|
||||
NEZHA_HOST = "192.178.7.123:8008"
|
||||
SCHEME = "ws"
|
||||
)
|
23
go.mod
Normal file
23
go.mod
Normal file
@ -0,0 +1,23 @@
|
||||
module git.mmeiblog.cn/mei/nezha-recoder
|
||||
|
||||
go 1.23.4
|
||||
|
||||
require (
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/mattn/go-sqlite3 v1.14.32
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
modernc.org/sqlite v1.38.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
modernc.org/libc v1.66.3 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
)
|
55
go.sum
Normal file
55
go.sum
Normal file
@ -0,0 +1,55 @@
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
|
||||
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o=
|
||||
golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||
modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM=
|
||||
modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
|
||||
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
|
||||
modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM=
|
||||
modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
||||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
|
||||
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
|
||||
modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ=
|
||||
modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.38.2 h1:Aclu7+tgjgcQVShZqim41Bbw9Cho0y/7WzYptXqkEek=
|
||||
modernc.org/sqlite v1.38.2/go.mod h1:cPTJYSlgg3Sfg046yBShXENNtPrWrDX8bsbAQBzgQ5E=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
26
internal/database.go
Normal file
26
internal/database.go
Normal file
@ -0,0 +1,26 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
func HandleSqlConnection() *sql.DB {
|
||||
db, err := sql.Open("sqlite", "sql.db")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// 设置连接池参数
|
||||
db.SetMaxOpenConns(25)
|
||||
db.SetMaxIdleConns(25)
|
||||
|
||||
// 验证数据库连接是否可用
|
||||
if err := db.Ping(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
63
internal/recoder.go
Normal file
63
internal/recoder.go
Normal file
@ -0,0 +1,63 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"git.mmeiblog.cn/mei/nezha-recoder/pkg"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
func Recoder() {
|
||||
servers := pkg.GetData()
|
||||
for _, server := range servers.Servers {
|
||||
checkNameChange(server)
|
||||
db := HandleSqlConnection()
|
||||
defer db.Close()
|
||||
|
||||
var diskUse float64
|
||||
if server.Host.Disk_total != 0 {
|
||||
diskUse = float64(server.State.Disk_used) / float64(server.Host.Disk_total) * 100
|
||||
} else {
|
||||
diskUse = 0 // 或者根据业务需求设置其他默认值
|
||||
}
|
||||
|
||||
sql := "INSERT INTO history (id, cpu, timestamp, disk_use, load_5, net_in_speed, net_out_speed, process_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
_, err := db.Exec(sql, server.Id, server.State.Cpu, time.Now().Unix(), diskUse, server.State.Load_5, server.State.Net_in_speed, server.State.Net_out_speed, server.State.Process_count)
|
||||
if err != nil {
|
||||
log.Println("insert error:", err)
|
||||
}
|
||||
log.Printf("写入数据成功: %s", server.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func checkNameChange(server pkg.Servers) {
|
||||
db := HandleSqlConnection()
|
||||
defer db.Close()
|
||||
|
||||
Query := "SELECT name FROM agent WHERE id = ?"
|
||||
var name string
|
||||
err := db.QueryRow(Query, server.Id).Scan(&name)
|
||||
if err == sql.ErrNoRows {
|
||||
addServer(server)
|
||||
} else if err != nil {
|
||||
log.Println("query error:", err)
|
||||
}
|
||||
|
||||
if name != server.Name {
|
||||
sql := "UPDATE agent SET name = ? WHERE id = ?"
|
||||
db.Exec(sql, server.Name, server.Id)
|
||||
}
|
||||
}
|
||||
|
||||
func addServer(server pkg.Servers) {
|
||||
db := HandleSqlConnection()
|
||||
defer db.Close()
|
||||
|
||||
sql := "INSERT INTO agent (id, name, disk_total, mem_total, arch, platform) VALUES (?, ?, ?, ?, ?, ?)"
|
||||
_, err := db.Exec(sql, server.Id, server.Name, server.Host.Disk_total, server.Host.Mem_total, server.Host.Arch, server.Host.Platform)
|
||||
if err != nil {
|
||||
log.Println("add Server error:", err)
|
||||
}
|
||||
}
|
26
main.go
Normal file
26
main.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"git.mmeiblog.cn/mei/nezha-recoder/internal"
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
func main() {
|
||||
internal.Recoder()
|
||||
c := cron.New()
|
||||
|
||||
c.AddFunc("@every 1h", internal.Recoder)
|
||||
|
||||
c.Start()
|
||||
|
||||
sig := make(chan os.Signal, 1)
|
||||
signal.Notify(sig, os.Interrupt, syscall.SIGTERM)
|
||||
<-sig // 阻塞直到收到信号
|
||||
fmt.Printf("Hava a good Day!")
|
||||
c.Stop() // 关闭 cron
|
||||
}
|
65
pkg/nezha.go
Normal file
65
pkg/nezha.go
Normal file
@ -0,0 +1,65 @@
|
||||
package pkg
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/url"
|
||||
|
||||
"git.mmeiblog.cn/mei/nezha-recoder/configs"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
// Struct
|
||||
type Message struct {
|
||||
Now int64 `json:"now"` // timestamp
|
||||
Online int `json:"online"` // online number
|
||||
Servers []Servers `json:"servers"`
|
||||
}
|
||||
|
||||
type Servers struct {
|
||||
Id int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Host Host `json:"host"`
|
||||
State State `json:"state"`
|
||||
}
|
||||
|
||||
type Host struct {
|
||||
Disk_total int `json:"disk_total"`
|
||||
Mem_total int `json:"mem_total"`
|
||||
Arch string `json:"arch"`
|
||||
Platform string `json:"platform"`
|
||||
}
|
||||
|
||||
type State struct {
|
||||
Cpu float64 `json:"cpu"`
|
||||
Disk_used int `json:"disk_used"`
|
||||
Load_5 float32 `json:"load_5"`
|
||||
Net_in_speed int `json:"net_in_speed"`
|
||||
Net_out_speed int `json:"net_out_speed"`
|
||||
Process_count int `json:"process_count"`
|
||||
}
|
||||
|
||||
func GetData() (servers Message) {
|
||||
u := url.URL{Scheme: configs.SCHEME, Host: configs.NEZHA_HOST, Path: "/api/v1/ws/server"}
|
||||
|
||||
conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
||||
if err != nil {
|
||||
log.Fatal("dial error:", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, data, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
log.Fatal("read error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
var msg Message
|
||||
if err = json.Unmarshal(data, &msg); err != nil {
|
||||
log.Println("json parse error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
return msg
|
||||
}
|
Loading…
Reference in New Issue
Block a user