88 "gorm.io/driver/sqlite"
99 "gorm.io/gorm"
1010
11+ "github.com/jinzhu/copier"
1112 "github.com/xos/serverstatus/model"
1213 "github.com/xos/serverstatus/pkg/utils"
1314)
@@ -39,6 +40,9 @@ func LoadSingleton() {
3940 loadAPI ()
4041 initNAT ()
4142 initDDNS ()
43+
44+ // 添加定时检查在线状态的任务,每分钟检查一次
45+ Cron .AddFunc ("*/1 * * * *" , CheckServerOnlineStatus )
4246}
4347
4448// InitConfigFromPath 从给出的文件路径中加载配置
@@ -69,6 +73,21 @@ func InitDBFromPath(path string) {
6973 if err != nil {
7074 panic (err )
7175 }
76+
77+ // 检查并添加新字段
78+ if ! DB .Migrator ().HasColumn (& model.Server {}, "cumulative_net_in_transfer" ) {
79+ err = DB .Migrator ().AddColumn (& model.Server {}, "cumulative_net_in_transfer" )
80+ if err != nil {
81+ log .Println ("NG>> 添加cumulative_net_in_transfer字段失败:" , err )
82+ }
83+ }
84+
85+ if ! DB .Migrator ().HasColumn (& model.Server {}, "cumulative_net_out_transfer" ) {
86+ err = DB .Migrator ().AddColumn (& model.Server {}, "cumulative_net_out_transfer" )
87+ if err != nil {
88+ log .Println ("NG>> 添加cumulative_net_out_transfer字段失败:" , err )
89+ }
90+ }
7291}
7392
7493// RecordTransferHourlyUsage 对流量记录进行打点
@@ -78,7 +97,13 @@ func RecordTransferHourlyUsage() {
7897 now := time .Now ()
7998 nowTrimSeconds := time .Date (now .Year (), now .Month (), now .Day (), now .Hour (), 0 , 0 , 0 , now .Location ())
8099 var txs []model.Transfer
100+ var serversToUpdate []model.Server
101+
81102 for id , server := range ServerList {
103+ if server .State == nil {
104+ continue
105+ }
106+
82107 tx := model.Transfer {
83108 ServerID : id ,
84109 In : utils .Uint64SubInt64 (server .State .NetInTransfer , server .PrevTransferInSnapshot ),
@@ -89,13 +114,33 @@ func RecordTransferHourlyUsage() {
89114 }
90115 server .PrevTransferInSnapshot = int64 (server .State .NetInTransfer )
91116 server .PrevTransferOutSnapshot = int64 (server .State .NetOutTransfer )
117+
118+ // 每次记录时更新累计流量到数据库
119+ if server .State .NetInTransfer > 0 || server .State .NetOutTransfer > 0 {
120+ serversToUpdate = append (serversToUpdate , model.Server {
121+ Common : model.Common {ID : id },
122+ CumulativeNetInTransfer : server .State .NetInTransfer ,
123+ CumulativeNetOutTransfer : server .State .NetOutTransfer ,
124+ })
125+ }
126+
92127 tx .CreatedAt = nowTrimSeconds
93128 txs = append (txs , tx )
94129 }
95- if len (txs ) == 0 {
96- return
130+
131+ if len (txs ) > 0 {
132+ log .Println ("NG>> Cron 流量统计入库" , len (txs ), DB .Create (txs ).Error )
133+ }
134+
135+ // 批量更新累计流量数据
136+ if len (serversToUpdate ) > 0 {
137+ for _ , server := range serversToUpdate {
138+ DB .Model (& server ).Updates (map [string ]interface {}{
139+ "cumulative_net_in_transfer" : server .CumulativeNetInTransfer ,
140+ "cumulative_net_out_transfer" : server .CumulativeNetOutTransfer ,
141+ })
142+ }
97143 }
98- log .Println ("NG>> Cron 流量统计入库" , len (txs ), DB .Create (txs ).Error )
99144}
100145
101146// CleanMonitorHistory 清理无效或过时的 监控记录 和 流量记录
@@ -154,3 +199,35 @@ func IPDesensitize(ip string) string {
154199 }
155200 return utils .IPDesensitize (ip )
156201}
202+
203+ // CheckServerOnlineStatus 检查服务器在线状态,将超时未上报的服务器标记为离线
204+ func CheckServerOnlineStatus () {
205+ ServerLock .Lock ()
206+ defer ServerLock .Unlock ()
207+
208+ now := time .Now ()
209+ offlineTimeout := time .Minute * 2 // 2分钟无心跳视为离线
210+
211+ for _ , server := range ServerList {
212+ // 已经标记为在线且长时间未活动,标记为离线
213+ if server .IsOnline && now .Sub (server .LastActive ) > offlineTimeout {
214+ server .IsOnline = false
215+
216+ // 如果还没有保存离线前状态,保存当前状态
217+ if server .LastStateBeforeOffline == nil && server .State != nil {
218+ lastState := model.HostState {}
219+ if err := copier .Copy (& lastState , server .State ); err == nil {
220+ server .LastStateBeforeOffline = & lastState
221+ }
222+ }
223+
224+ // 离线前保存累计流量数据到数据库
225+ if server .State != nil {
226+ DB .Model (server ).Updates (map [string ]interface {}{
227+ "cumulative_net_in_transfer" : server .State .NetInTransfer ,
228+ "cumulative_net_out_transfer" : server .State .NetOutTransfer ,
229+ })
230+ }
231+ }
232+ }
233+ }
0 commit comments