2022-01-08 22:54:14 -05:00
package singleton
2019-12-08 03:59:58 -05:00
import (
2022-04-14 04:41:34 -04:00
"log"
2022-03-18 11:45:03 -04:00
"time"
2019-12-09 05:14:31 -05:00
2019-12-08 03:59:58 -05:00
"github.com/patrickmn/go-cache"
2022-04-14 04:41:34 -04:00
"gorm.io/driver/sqlite"
2020-12-19 10:11:16 -05:00
"gorm.io/gorm"
2019-12-08 03:59:58 -05:00
2024-11-28 06:38:54 -05:00
"github.com/nezhahq/nezha/model"
"github.com/nezhahq/nezha/pkg/utils"
2019-12-08 03:59:58 -05:00
)
2023-11-28 10:01:37 -05:00
var Version = "debug"
2020-12-19 23:18:27 -05:00
2021-01-23 20:41:35 -05:00
var (
Conf * model . Config
Cache * cache . Cache
DB * gorm . DB
2022-03-18 11:45:03 -04:00
Loc * time . Location
2021-01-23 20:41:35 -05:00
)
2021-01-18 20:59:04 -05:00
2022-10-12 11:06:25 -04:00
func InitTimezoneAndCache ( ) {
2022-03-18 11:45:03 -04:00
var err error
2022-10-12 11:06:25 -04:00
Loc , err = time . LoadLocation ( Conf . Location )
2022-03-18 11:45:03 -04:00
if err != nil {
panic ( err )
}
2021-01-08 08:04:50 -05:00
2022-04-12 01:16:33 -04:00
Cache = cache . New ( 5 * time . Minute , 10 * time . Minute )
2021-01-08 08:04:50 -05:00
}
2021-01-23 20:41:35 -05:00
2022-04-12 01:16:33 -04:00
// LoadSingleton 加载子服务并执行
func LoadSingleton ( ) {
2024-10-31 17:07:04 -04:00
initI18n ( ) // 加载本地化服务
2024-07-14 07:41:50 -04:00
loadNotifications ( ) // 加载通知服务
loadServers ( ) // 加载服务器列表
loadCronTasks ( ) // 加载定时任务
initNAT ( )
2024-10-17 09:03:03 -04:00
initDDNS ( )
2021-01-23 20:41:35 -05:00
}
2021-06-21 09:30:42 -04:00
2022-04-12 01:16:33 -04:00
// InitConfigFromPath 从给出的文件路径中加载配置
func InitConfigFromPath ( path string ) {
2022-04-27 22:17:38 -04:00
Conf = & model . Config { }
2022-04-12 01:16:33 -04:00
err := Conf . Read ( path )
if err != nil {
panic ( err )
2021-06-21 09:30:42 -04:00
}
}
2022-02-19 01:29:06 -05:00
2022-04-12 01:16:33 -04:00
// InitDBFromPath 从给出的文件路径中加载数据库
func InitDBFromPath ( path string ) {
var err error
DB , err = gorm . Open ( sqlite . Open ( path ) , & gorm . Config {
CreateBatchSize : 200 ,
} )
if err != nil {
panic ( err )
}
if Conf . Debug {
DB = DB . Debug ( )
}
2024-10-28 02:42:36 -04:00
err = DB . AutoMigrate ( model . Server { } , model . User { } , model . ServerGroup { } , model . NotificationGroup { } ,
model . Notification { } , model . AlertRule { } , model . Service { } , model . NotificationGroupNotification { } ,
model . ServiceHistory { } , model . Cron { } , model . Transfer { } , model . ServerGroupServer { } , model . UserGroup { } ,
2024-11-22 10:57:25 -05:00
model . UserGroupUser { } , model . NAT { } , model . DDNSProfile { } , model . NotificationGroupNotification { } ,
model . WAF { } )
2022-04-12 01:16:33 -04:00
if err != nil {
panic ( err )
2022-02-19 01:29:06 -05:00
}
}
2022-04-14 04:41:34 -04:00
// RecordTransferHourlyUsage 对流量记录进行打点
func RecordTransferHourlyUsage ( ) {
ServerLock . Lock ( )
defer ServerLock . Unlock ( )
now := time . Now ( )
2024-07-04 02:32:19 -04:00
nowTrimSeconds := time . Date ( now . Year ( ) , now . Month ( ) , now . Day ( ) , now . Hour ( ) , 0 , 0 , 0 , now . Location ( ) )
2022-04-14 04:41:34 -04:00
var txs [ ] model . Transfer
for id , server := range ServerList {
tx := model . Transfer {
ServerID : id ,
2024-08-10 22:35:19 -04:00
In : utils . Uint64SubInt64 ( server . State . NetInTransfer , server . PrevTransferInSnapshot ) ,
Out : utils . Uint64SubInt64 ( server . State . NetOutTransfer , server . PrevTransferOutSnapshot ) ,
2022-04-14 04:41:34 -04:00
}
if tx . In == 0 && tx . Out == 0 {
continue
}
2024-08-10 22:35:19 -04:00
server . PrevTransferInSnapshot = int64 ( server . State . NetInTransfer )
server . PrevTransferOutSnapshot = int64 ( server . State . NetOutTransfer )
2022-04-14 04:41:34 -04:00
tx . CreatedAt = nowTrimSeconds
txs = append ( txs , tx )
}
if len ( txs ) == 0 {
return
}
log . Println ( "NEZHA>> Cron 流量统计入库" , len ( txs ) , DB . Create ( txs ) . Error )
}
2024-10-24 12:13:45 -04:00
// CleanServiceHistory 清理无效或过时的 监控记录 和 流量记录
func CleanServiceHistory ( ) {
2022-04-14 04:41:34 -04:00
// 清理已被删除的服务器的监控记录与流量记录
2024-10-24 12:13:45 -04:00
DB . Unscoped ( ) . Delete ( & model . ServiceHistory { } , "created_at < ? OR service_id NOT IN (SELECT `id` FROM services)" , time . Now ( ) . AddDate ( 0 , 0 , - 30 ) )
2024-02-12 01:16:04 -05:00
// 由于网络监控记录的数据较多,并且前端仅使用了 1 天的数据
// 考虑到 sqlite 数据量问题,仅保留一天数据,
// server_id = 0 的数据会用于/service页面的可用性展示
2024-10-24 12:13:45 -04:00
DB . Unscoped ( ) . Delete ( & model . ServiceHistory { } , "(created_at < ? AND server_id != 0) OR service_id NOT IN (SELECT `id` FROM services)" , time . Now ( ) . AddDate ( 0 , 0 , - 1 ) )
2022-04-14 04:41:34 -04:00
DB . Unscoped ( ) . Delete ( & model . Transfer { } , "server_id NOT IN (SELECT `id` FROM servers)" )
// 计算可清理流量记录的时长
var allServerKeep time . Time
specialServerKeep := make ( map [ uint64 ] time . Time )
var specialServerIDs [ ] uint64
var alerts [ ] model . AlertRule
DB . Find ( & alerts )
2022-04-14 15:13:53 -04:00
for _ , alert := range alerts {
for _ , rule := range alert . Rules {
2022-04-14 04:41:34 -04:00
// 是不是流量记录规则
2022-04-14 15:13:53 -04:00
if ! rule . IsTransferDurationRule ( ) {
2022-04-14 04:41:34 -04:00
continue
}
2024-07-04 02:32:19 -04:00
dataCouldRemoveBefore := rule . GetTransferDurationStart ( ) . UTC ( )
2022-04-14 04:41:34 -04:00
// 判断规则影响的机器范围
2022-04-14 15:13:53 -04:00
if rule . Cover == model . RuleCoverAll {
2022-04-14 04:41:34 -04:00
// 更新全局可以清理的数据点
if allServerKeep . IsZero ( ) || allServerKeep . After ( dataCouldRemoveBefore ) {
allServerKeep = dataCouldRemoveBefore
}
} else {
// 更新特定机器可以清理数据点
2022-04-14 15:13:53 -04:00
for id := range rule . Ignore {
2022-04-14 04:41:34 -04:00
if specialServerKeep [ id ] . IsZero ( ) || specialServerKeep [ id ] . After ( dataCouldRemoveBefore ) {
specialServerKeep [ id ] = dataCouldRemoveBefore
specialServerIDs = append ( specialServerIDs , id )
}
}
}
}
}
for id , couldRemove := range specialServerKeep {
2024-07-04 02:32:19 -04:00
DB . Unscoped ( ) . Delete ( & model . Transfer { } , "server_id = ? AND datetime(`created_at`) < datetime(?)" , id , couldRemove )
2022-04-14 04:41:34 -04:00
}
if allServerKeep . IsZero ( ) {
DB . Unscoped ( ) . Delete ( & model . Transfer { } , "server_id NOT IN (?)" , specialServerIDs )
} else {
2024-07-04 02:32:19 -04:00
DB . Unscoped ( ) . Delete ( & model . Transfer { } , "server_id NOT IN (?) AND datetime(`created_at`) < datetime(?)" , specialServerIDs , allServerKeep )
2022-04-14 04:41:34 -04:00
}
}
// IPDesensitize 根据设置选择是否对IP进行打码处理 返回处理后的IP(关闭打码则返回原IP)
func IPDesensitize ( ip string ) string {
if Conf . EnablePlainIPInNotification {
return ip
}
return utils . IPDesensitize ( ip )
}